Home > Back-end >  Angular Data binding repeated
Angular Data binding repeated

Time:01-27

I created a form. Then I added a link to add a section like previous

image1

when clicked add another address, it displayed address 2 form

image2

Then I clicked the first input field, the validations errors are displayed in 2nd form also

image3

how to fix this?

app.component.html

<label for="line1">STREET 1</label>
   <input id="line1" type="text" formControlName="line1" required/>
   <error-component
      [control]="formAddress.controls.line1">
   </error-component>

app.component.ts

formAddress = this.formBuilder.group({
    line1: ["", Validators.required],
    line2: '',
    postalCode: ["", Validators.required],
  });

CodePudding user response:

Your problem is that you only are repeating the "same" FormGroup. (check your code to see that you have an unique formGroup. Remember that if we have an array and use some like:

  formGrup="..."
  array=[this.formGroup]
  //in any place
  array.push(this.formGroup)

  //the two elements of the array is the same formGroup!!!

One Solution: The idea is use a FormArray of FormGroups (another one it's use an Array of FormGroup)

When we have an array of FormGroups we create a function that return a FormGroup

createAddressGroup()
{
  return new FormGroup({
    line1:new FormControl("", Validators.required),
    line2: new FormControl(''),
    postalCode: new FormControl("", Validators.required),
  })
}

And we create de he formArray, and create a function to add a new FormGroup to the array and another one to delete

formArray=new FormArray([this.createAddressGroup()])

addAddress()
{
   this.formArray.push(this.createAddressGroup());
}
removeAddress(index:number)
{
   this.formArray.removeAt(index);
}

When mannage a FormArray not inside a FormGroup we need create a function that return the formGroup

getAddress(index:number)
{
   return this.formArray.at(index) as FormGroup
}

Well, it's all ready to create the .html

<!--see that iterate over formArray.controls, and we indicate
    the formGroup using formGroup]="getAddress(i)"-->
<fieldset *ngFor="let group of formArray.controls;let i=index"
     [formGroup]="getAddress(i)">
     <legend>{{'Address ' (i 1)}}</leyend>
     <div>
        <label for="email">Street 1</label>
        <input id="email" formControlName="line1" />
        <div >
            * Required
        </div>
    </div>
     <div>
        <label for="email">Street 2</label>
        <input id="email" formControlName="line2" />
    </div>
     <div>
        <label for="email">Country</label>
        <input id="email" formControlName="postalCode" />
        <div >
            * Required
        </div>
    </div>
</fieldset>

Where I'm using the .css showed in this SO and this stackblitz

.invalid-feedback
{
   display:none
}
.ng-invalid.ng-touched ~ .invalid-feedback
{
  display: block;
}

CodePudding user response:

You have to use the index from "over array iteration" to build "for" and "id" attributes of each field. Like

<ng-container formArrayName="files">
    ...
    <ng-container [formGroupName]="i">

            <label [for]="'file_name_'   i.toString()">
              {{ "contents.practice.fields.files.name" | translate }}
            </label>
            <div >
              <input
                pInputText
                [id]="'file_name_'   i.toString()"
                type="text"
                formControlName="name"
                autocomplete="off"
                
              />
            </div>
  • Related