2017-07-17 2 views
0

J'essaie de créer ma première application angulaire 2. Et comme d'habitude je suis immédiatement en difficulté avec le modèle que je veux créer. J'ai un modèle pour créer une relation parent-enfant entre les artilces. Par exemple: Je veux ajouter un article à mon panier avec quelques objets enfants comme suit:Formes réactives angulaires 2/4 avec des tableaux

IArticle[] = [ 
{ 
    id: 1, 
    parentArticle: 1234596, 
    description: 'some description for parent' 
    children: [ 
     { 
      id: 1, 
      childArticle: 123457, 
      childDescription: 'some description for first child' 
     }, 
     { 
      id: 2, 
      childArticle: 123467, 
      childDescription: 'some description for second child' 
     }, 
     ..... 
    ] 

dactylographiée je défini une interface pour mon article. Les objets enfants ont leur propre interface légèrement différente. Parce que ces objets enfants sont un petit ensemble fixe, je veux ajouter ces enfants en utilisant une liste déroulante. Je veux que ces objets s'affichent sous la forme de boutons avec un retrait quand on clique dessus (facultatif avec un popup modal avec la question "êtes-vous sûr"). J'ai donc pensé que le bouton à côté de la liste déroulante devrait ajouter la valeur dropdownlist au tableau. Cela fonctionne correctement lorsque j'ai ajouté les valeurs à un tableau typé normal. Mais maintenant je veux envelopper ce tableau dans une "forme réactive".

Quelqu'un peut-il m'aider à travailler avec des tableaux dans ces formulaires réactifs et à les envelopper dans un objet formcontrol. J'ai regardé le "contrôle" FormArray mais je ne suis pas sûr que c'est ce que je cherche. Il semble un tableau de FormControls, pas un tableau de données. Peut-être que les formulaires réactifs ne sont pas la bonne décision? J'espère que quelqu'un pourra me mettre sur la bonne voie.

Mon modèle html est comme suit (code de démarrage dépouillé du code)

<form autocomplete="off"> 
     <input type="text" Placeholder="Article Number" /> 
    <div > 
     <button *ngFor="let child of children"> 
     <span class="glyphicon glyphicon-remove-circle text-danger"></span> 
     {{ child.childArticle }} 
     </button> 
    </div> 
    <div > 
     <select class="form-control inline"> 
      <option value="">Select Service..</option> 
      <option *ngFor="let serviceOption of serviceOptions" [ngValue]="serviceOption.serviceNumber"> 
       {{serviceOption.serviceDescription}} 
      </option> 
     </select> 
      <button (click)="onAddService()"> 
      Add 
      </button> 
    </div> 
    <div> 
     <button type="submit"> 
     Save 
     </button> 
    </div> 
    </form> 

Cordialement.

------ Code tapuscrit:

export class NewServiceComponent implements OnInit { 
    newServiceForm: FormGroup; 
    serviceOptions: IServiceArticle[] = [ 
    { 'id': 1, 'serviceNumber': 123456, serviceDescription: 'description 1' }, 
    { 'id': 2, 'serviceNumber': 456789, serviceDescription: 'description 2' }, 
    { 'id': 3, 'serviceNumber': 123456, serviceDescription: 'description 3' }, 
]; 
selectedServiceOption: IServiceArticle; 
newArticle: IService; 

constructor(private _fb: FormBuilder) { 
} 

createForm() { 
this.newServiceForm = this._fb.group({ 
    services: this._fb.array([]), 
    articleNumber: this._fb.control(null, Validators.required), 
}) 
} 

ngOnInit() { 
    this.createForm(); 
} 

onAddService() { 
    const arrayControl = <FormArray>this.newServiceForm.controls['services']; 
    let newgroup = this._fb.group({ 
    serviceNumber: this.selectedServiceOption.serviceNumber, 
    serviceDescription: this.selectedServiceOption.serviceDescription, 
    }) 
    arrayControl.push(newgroup); 
} 
} 
+0

Je me demandais juste à propos du 'select', cela pourrait signifier que l'utilisateur pourrait choisir la même valeur encore et encore? – Alex

+0

à ce moment, il pourrait. La logique de validation doit être mise à jour pour éviter cela. Pour ma compréhension de l'angulaire, ce n'est pas un problème en ce moment. –

+0

Hé, comment ça s'est passé avec les réponses? Est-ce que vous avez aidé ou avez-vous besoin d'aide supplémentaire? :) – Alex

Répondre

0

Lors de la création d'une forme réactive, vous devez d'abord le groupe de forme principale et vous aurez un contrôle formArray au sein du groupe de forme. Après cela, vous ajouterez tous les enfants existants à ce formArray et chacun de ces enfants sera son propre formGroup.

constructor(private fb: FormBuilder){ 
    myTypeScriptChildrenObjects = functionToGetTheChildrenArray(); 
} 
... 

createForm(){ 
    this.form = this.fb.group({ 
     childrenArray: this.fb.array([]) 
    }) 

    const arrayControl = <FormArray>this.orderForm.controls['childrenArray']; 
    this.myTypeScriptChildrenObjects.forEach(item => { 
     let newGroup = this.fb.group({ 
      prop1: [item.prop1], 
      prop2: [item.prop2], 
      prop3: [item.prop3] 
     }) 
     arrayControl.push(newGroup); 
    }) 
} 

Lorsque le vélo à travers ceux-ci dans votre code html vous faites quelque chose comme ceci:

<select formArrayName="childrenArray"> 
      <option [formGroupName]="i" *ngFor="let line of form.controls['childrenArray'].controls; index as i" text="prop1" value="prop2"> 
+0

Désolé, mais avec ma connaissance de l'angulaire votre réponse n'est pas suffisante. J'ai plusieurs erreurs. J'ai essayé différentes choses mais je ne sais pas où chercher. J'ai ajouté la directive [formGroup] = "formnameintypescipt" au formulaire. ERREUR: FormGroupName doit être utilisé avec une directive parent formGroup. Vous devez ajouter une directive formGroup et lui passer une instance FormGroup existante (vous pouvez en créer une dans votre classe). –

+0

C'est la bonne approche, dans les formes réactives, vous devriez vous concentrer sur la création des contrôles du côté logique et utiliser les directives structurelles pour les mapper au modèle. – LookForAngular

+0

Votre nom de formulaire est-il une variable dans votre composant? – LookForAngular

0

Essayé le code suivant et il semble fonctionner comme il se doit ....

En ce qui concerne la forme, vous aurez besoin d'ajouter le [formGroup], donc:

<form [formGroup]="newServiceForm"> 

et puisque c'est dans une fo rmgroup maintenant, il n'acceptera pas [(ngModel)] pour le select sans un contrôle de formulaire. Nous pouvons contourner cela avec l'aide [ngModelOptions]="{standalone: true}"

aussi je puis changer le [ngValue] de se référer à l'objet: [ngValue]="serviceOption"

Ensuite, nous ajoutons la valeur sélectionnée et pousser au tableau de forme, comme vous l'avez fait.

Dans le modèle, nous voulons maintenant itérer ce tableau de forme.Dans l'ensemble, le modèle devrait ressembler à ceci:

<form [formGroup]="newServiceForm"> 
    <div formArrayName="services"> 
    <button *ngFor="let child of newServiceForm.controls.services.controls; 
     let i = index" [formGroupName]="i"> 
     <span [innerHtml]="child.controls.serviceDescription.value"> </span> 
    </button> 
    </div> 

<select [(ngModel)]="selectedServiceOption" [ngModelOptions]="{standalone: true}"> 
    <option>Select Service..</option> 
    <option *ngFor="let serviceOption of serviceOptions" [ngValue]="serviceOption"> 
      {{serviceOption.serviceDescription}} 
    </option> 
</select> 
<button (click)="onAddService()"> Add </button> 
</form> 

Les contrôles de formulaire peuvent également être configurés pour les variables afin que vous puissiez éviter ces longs chemins. Et comme discuté dans les commentaires, cela ne prend pas en considération le fait que l'utilisateur peut choisir la même valeur encore et encore, mais ce n'était pas pertinent en question.