2017-07-24 2 views
1

J'utilise le motif de forme dynamique en Angulaire avec diverses formes que nous avons. C'est un moyen pratique pour nous car nous avons seulement besoin de définir nos contrôles dans ngOnInit et il va construire dynamiquement la forme dont nous avons besoin. Cependant, il existe certaines formes que les valeurs doivent être initialisées et certaines des valeurs peuvent être récupérées en utilisant async/await.Comment faire pour que les données asynchrones fonctionnent avec un motif de forme dynamique en angulaire

Il s'agit d'un problème avec la forme dynamique car lorsque j'initialise des données asynchrones, elle renvoie des erreurs sur la console et le formulaire n'apparaît pas sur la vue.

J'ai essayé d'ajouter async sur le ngOnInit et j'attends les données asynchrones. Comme l'exemple de code ci-dessous montre:

async ngOnInit() { 
    const pageUrl = await this.fooService.getTabUrl(); 
    const security = this.barService.getSecurity(); 

    const controls: Array<ControlBase<any>> = [ 
     new ControlTextbox({ 
      key: "url", 
      order: 0, 
      readonly: true, 
      type: "text", 
      value: pageUrl 
     }), 
     new ControlDropdown({ 
      key: "security", 
      label: "Security", 
      order: 2, 
      options: security, 
      type: "dropdown", 
      value: security[0].id 
     }) 
    ]; 
    this.controls = controls; 
} 

ajouter également un tuyau async sur la vue:

<form class="{{formClass}}" (ngSubmit)="onSubmit()" [formGroup]="form" role="form"> 
    <app-form-control *ngFor="let ctrl of controls | async" [control]="ctrl | async" [form]="form | async"></app-form-control> 
    <div class="form-group"> 
     <button type="submit" class="btn btn-primary btn-block" [disabled]="!form.valid">{{btnText}}</button> 
    </div> 
</form> 

Toutefois, cela ne fonctionne pas.

Pour plus de détails s'il vous plaît voir la capture d'écran. enter image description here

codes supplémentaires:

export class FormControlComponent implements OnInit { 
    @Input() public control: ControlBase<string | boolean | undefined>; 
    @Input() public form: FormGroup; 

    constructor() { } 

    get valid() { 
     return this.form.controls[this.control.key].valid; 
    } 

    get invalid() { 
     return !this.form.controls[this.control.key].valid && this.form.controls[this.control.key].touched; 
    } 

    ngOnInit() { } 
} 

export class DynamicFormComponent implements OnInit { 
    @Input() public controls: Array<ControlBase<any>> = []; 
    @Input() public btnText = "Submit"; 
    @Output() public formSubmit: EventEmitter<any> = new EventEmitter<any>(); 
    public form: FormGroup; 

    constructor(public _controlService: FormControlService) { } 

    ngOnInit() { 
     const sortedControls = this.controls.sort((a, b) => a.order - b.order); 
     this.form = this._controlService.toControlGroup(sortedControls); 
    } 

    onSubmit(): void { 
     this.formSubmit.emit(this.form.value); 
    } 
} 

export class FormControlService { 
    constructor() { } 

    public toControlGroup(controls: Array<ControlBase<any>>) { 
     const group: any = {}; 

     controls.forEach(control => { 
      const validators: any = []; 

      // Required 
      if (control.required) { 
       validators.push(Validators.required); 
      } 

      // remove for brevity 

      group[control.key] = new FormControl(control.value || "", validators); 
     }); 

     return new FormGroup(group); 
    } 
} 

Je suis encore nouveau et l'apprentissage angulaire. Toute suggestion sur la façon dont je vais surmonter le problème lors de l'initialisation des données asynchrones?

+0

Qu'est-ce que votre 'FormControlService.toControlGroup () 'retour? On dirait que votre formulaire doit être un 'FormGroup' mais c'est quelque chose d'autre. Je reçois généralement cette erreur lorsque j'ajoute '[formGroup] =" form "' à mon formulaire, où 'form' n'est pas défini sur la bonne valeur/type. Assurez-vous également que les contrôles que vous bouclez ont également un ensemble '[formGroup]' approprié, car ils en ont besoin également et cette erreur peut être levée pour ceux-là aussi. – Lansana

+0

@Lansana J'ai mis à jour ma question – rpmansion

Répondre

2

Je vais généralement ajouter une instruction ngIf sur l'élément de formulaire s'il attend des données asynchrones ou si le formulaire est particulièrement complexe. Fondamentalement, ce qui se passe, et je pense que vous le savez déjà, c'est que le formulaire ne s'initialise pas à temps pour battre la page affichée à l'écran. Selon les circonstances, il peut arriver que l'erreur soit parfois rejetée. En ajoutant:

<form *ngIf="form"> 

Vous force angulaire d'attendre jusqu'à ce que form a été instancié. L'autre problème que je vois pourrait être dû au fait que vous pré-remplissez vos contrôles de formulaire pendant le processus d'instanciation de formulaire en utilisant des données asynchrones. Cela ne va généralement pas très bien. Une meilleure façon (sauf si vous avez les données à portée de main immédiatement), est d'instancier un formulaire emtpy, suivi d'un appel pour obtenir les données que vous voulez mettre dans le formulaire. Ensuite, utilisez les méthodes get() et setValue() pour remplir les contrôles de formulaire. Pour l'utilisateur, la différence n'est même pas perceptible, mais c'est une méthode beaucoup plus fiable de pré-remplissage des formulaires à mon avis. Par exemple, c'est ce que vous pourriez faire pour préremplir le « Nom du rôle utilisateur » d'un rôle utilisateur sous forme d'édition:

quelques-component.component.ts

ngOnInit() { 
    // Instantiate your form. 
    buildUserRoleFormGroup(); 
} 

buildUserRoleFormGroup() { 

    // INSTANTIATE YOUR FORM HERE..... 

    // Then populate it. 
    populateUserRoleForm(); 
} 

populateUserRoleForm() { 
    this._UserRolesService.getUserRole(this.userRoleID) 
     .subscribe(_UserRole => { 
      // Save the data to a component property 
      this.userRole = _UserRole.data; 

      // Get the user role name form control 
      let userRoleName = this.createUserRoleForm.get('userRoleName') 
      // Set the user role name form control value 
      userRoleName.setValue(this.userRole.userRoleName); 
      }, 
      _Error => { 
       console.log(_Error); 
      }) 
    } 
+0

idiote moi j'ai oublié en utilisant le * ngIf. J'ai réussi à le faire fonctionner mais sans utiliser le * ngIf pour vérifier le formulaire au lieu que je l'ai utilisé pour vérifier les contrôles. Je devrais faire un peu de lecture et de pratique sur votre dernière suggestion, mais si vous pouviez partager un exemple de code pour un aperçu? – rpmansion

+0

Je viens de mettre à jour ma réponse pour inclure un exemple de code sur l'obtention et la configuration des contrôles de formulaire. J'espère que cela aide. – joshrathke