Sunday, December 31, 2017

Sometimes you can't drill into a FormGroup in Angular 4 without breaking the chain in half midstream. It's corny!

Alright, this code is legit for slurping stuff back out of reactive forms:

submit(): void {
   let presidents:President[] = [];
   let formArray:any = this.presidentsForm.controls['lineItems'];
   formArray.controls.forEach((formGroup:FormGroup):void => {
      let president:President = new President;
      president.Name = formGroup.controls['name'].value;
      president.Party = formGroup.controls['party'].value;
      president.HasNonconsecutiveTerms =
            formGroup.controls['hasNonconsecutiveTerms'].value;
      presidents.push(president);
   });
   this.presidentialContract.setPresidents(presidents).toPromise().then(
      function(data) {
         window.location.href = "/#/list";
      }.bind(this),
      function(error){
         console.log(error);
      });
}

 
 

Why can't the second and third lines of the method be one line like so?

submit(): void {
   let presidents:President[] = [];
   this.presidentsForm.controls['lineItems'].controls.forEach((formGroup:FormGroup):void
         => {
      let president:President = new President;
      president.Name = formGroup.controls['name'].value;
      president.Party = formGroup.controls['party'].value;
      president.HasNonconsecutiveTerms =
            formGroup.controls['hasNonconsecutiveTerms'].value;
      presidents.push(president);
   });
   this.presidentialContract.setPresidents(presidents).toPromise().then(
      function(data) {
         window.location.href = "/#/list";
      }.bind(this),
      function(error){
         console.log(error);
      });
}

 
 

Well, if you don't break the chain midway you'll get an error like this:

Failed to compile.
C:/Apps/GroverClevelandHopscotch/src/GroverClevelandHopscotch.UserInterface/src/app/components/reactiveForms.component.ts (44,51): Property 'controls' does not exist on type 'AbstractControl'.

 
 

If you try to make formArray a FormArray instead of any, which is the type I used to originally create lineItems, you'll similarly get:

Failed to compile.
C:/Apps/GroverClevelandHopscotch/src/GroverClevelandHopscotch.UserInterface/src/app/components/reactiveForms.component.ts (43,13): Type 'AbstractControl' is not assignable to type 'FormArray'. Property 'controls' is missing in type 'AbstractControl'.

 
 

What is more, if you loop in AbstractControl from @angular/forms as an import and try to use it instead of any you get the first error. I don't see any way out of using any save for not declaring a type there which is basically the same thing and I hate using any. I feel dirty whenever I use any and I should. This is some pretty finicky, cantankerous stuff, huh? This won't work either:

submit(): void {
   let presidents:President[] = [];
   this.presidentsForm.controls.lineItems.controls.forEach((formGroup:FormGroup):void
         => {
      let president:President = new President;
      president.Name = formGroup.controls['name'].value;
      president.Party = formGroup.controls['party'].value;
      president.HasNonconsecutiveTerms =
            formGroup.controls['hasNonconsecutiveTerms'].value;
      presidents.push(president);
   });
   this.presidentialContract.setPresidents(presidents).toPromise().then(
      function(data) {
         window.location.href = "/#/list";
      }.bind(this),
      function(error){
         console.log(error);
      });
}

 
 

This will work, but Visual Studio Code 1.8.0 will put a squiggly red line under lineItems like it can't figure out what it is. The code will still compile and work however.

submit(): void {
   let presidents:President[] = [];
   let formArray:any = this.presidentsForm.controls.lineItems;
   formArray.controls.forEach((formGroup:FormGroup):void => {
      let president:President = new President;
      president.Name = formGroup.controls['name'].value;
      president.Party = formGroup.controls['party'].value;
      president.HasNonconsecutiveTerms =
            formGroup.controls['hasNonconsecutiveTerms'].value;
      presidents.push(president);
   });
   this.presidentialContract.setPresidents(presidents).toPromise().then(
      function(data) {
         window.location.href = "/#/list";
      }.bind(this),
      function(error){
         console.log(error);
      });
}

No comments:

Post a Comment