Angular2: submit new formGroup with model driven form

I’m a js novice learning angular2 and would be very grateful for any guidance on the following…

Adding to a FormArray via input field

To add values, via a form input, to an existing array I can use (click)=“addAddress()” in the html where addAddress is defined in the component.ts to update values in an array in the form AppComponent:

ngOnInit() {
        this.myForm = this._fb.group({
            name: ['', [Validators.required, Validators.minLength(5)]],
            addresses: this._fb.array([
                this.initAddress(),
            ])
        });
    }

    initAddress() {
        return this._fb.group({
            street: ['', Validators.required],
            postcode: ['']
        });
    }

    addAddress() {
        const control = <FormArray>this.myForm.controls['addresses'];
        control.push(this.initAddress());
    }

And back in the html ngFor is used to add a set of input fields each time the ‘add’ button is clicked":


 <div formArrayName="addresses">
          <div *ngFor="let address of myForm.controls.addresses.controls; let i=index" >
              <span>Address {{i + 1}}</span>
            <div [formGroupName]="i">
                <input type="text" formControlName="street">
                <input type="text" formControlName="postcode">
            </div>
          </div>
        </div>

The full working example here: https://embed.plnkr.co/sUjE1ULYhfDHLNBw2sRv/

Adding to form FormGroup via input field

I would like to understand how to add a completely new FormGroup via form input.
So taking the case of the example above…

Rather than adding to an array of addresses:

{
  "name": "",
  "addresses": [
    {
      "street": "Baker Street",
      "postcode": "w2"
    },
    {
      "street": "Bond Street",
      "postcode": "w1"
    }
  ]
}

Each time an address is added a new FormGroup is created where the user adds the FormGroupName for each via form input:

{  
   "name":"",
   "home":{  
      "street":"Baker Street",
      "postcode":"w2"
   },
   "work":{  
      "street":"Bond Street",
      "postcode":"w1"
   }
}

I have begun to adapt the original example and added a few questions where I’m unsure (which unfortunately turns out to be in a lot of places) but any pointers or direction would be gratefully received even just examples or the concepts to look at that will help me solve the problem! Thanks.

App.Component.ts

constructor(private _fb: FormBuilder) { }
    ngOnInit() {
        this.myForm = this._fb.group({
            name: ['', [Validators.required, Validators.minLength(5)]],
            // Each new adress to be added here 
           //e.g.
            /*
             home: this._fb.group({ 
              street: ['', Validators.required],
              postcode: ['']
              });
            */ 
            // Can this be done using this.initiAddress() here 
           // like in the original example?
        });
    }

// FormGroupName of the new FomGroup is defined by the 'address' submitted
// Hence added newAddressObj as an argument 
    initAddress(newAddressObj) {
// but how do I update the function to 
// return a named _fb.group to include newAddressObj? 
        return newAddressObj this._fb.group({
            street: ['', Validators.required],
            postcode: ['']
        });
    }

// Added 'address' as an argument. 
// 'address' being submitted via form input field
    addAddress(address:string) {

// The original example pushes to an existing FormArray: 
// <FormArray>this.myForm.controls['addresses']
// How can I add a new FormGroup this._fb.group directly? 
//Can I use form.controls.push to do this?:
        const control = <FormGroup>this.myForm.controls;
        control.push(this.initAddress(address));
    }

  // Will I need to add a new interface 
 // each time a new FormGroup is added?
    save(model: Customer) {
        // call API to save
        // ...
        console.log(model);
    }
}

App.Component.html


<!-- Here want to add a new FormGroup directly to form controls but how? -->
          <div *ngFor="let address of myForm.controls" >
       <!-- The new formGroupName 'address' is submitted by the user. -->
       <!-- What  do we use to replace address.value -->
       <!-- to access each new 'address' object name added by the user? -->
            <div formGroupName="address.value">
     <!-- Here want to reference the name of the new address object to display-->
              <span> {{ address.value }} </span>
            <div >
                <label>street</label>
                <input type="text" formControlName="street" 
                  [formControl]="address.value.controls.street">
                <label>postcode</label>
                <input type="text" formControlName="postcode" 
                  [formControl]="address.value.controls.postcode">
            </div>
          </div>
        </div>

<!-- The FormGroupName 'address' is now defined via form input; -->
          <input #address (keyup.enter)="addAddress(address.value)"
              (blur)="addAddress(address.value); address.value=''" >
<!-- The FormGroupName 'address' is added as an argument -->
          <button (click)="addAddress(address.value)">Add new Address</button>

I’ve studied a bit on Angular 2 and on RC4 they’ve changed a bit. Looks like you got it working and to get it to that format. I would create an object that has

street
postcode
type: ‘home’ or ‘work’

and still keep it as list. On the ‘submit’ implementation, you can change the input before sending out the server… For me, I would just send it as

{  
   "name":"",
   "addresses":[{  
      "type": "home",
      "street":"Baker Street",
      "postcode":"w2"
   },{  
      "type": "work",
      "street":"Bond Street",
      "postcode":"w1"
   }]
}

Thanks very much for your response.

To be honest I was just adapting the use case from the original working example to keep things simple but I would like to know how to solve it in the way proposed so that I can understand how to add a new formGroup to the controls - even though it would probably seem unnecessary in this example.

i.e.I mean my question is really about how you can add a new FormGroup to the form controls via input as apposed to solving a specific problem of wanting to submit a ‘type’ for the addresses in the example.

thanks

I see what you mean. I think you’re looking for ‘model driven form’ vs ‘template drive form’

Hopefully that helps.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.