Formas reactivas angulares 7: agregue/elimine dinámicamente campos de entrada para cada campo de entrada en el formulario

CorePress2024-01-24  12

Tengo que crear dinámicamente un formulario con datos recibidos del servidor con la opción de agregar y eliminar campos de entrada para cada campo de entrada existente.

Estos son los datos que recibo del servidor

documents = [{id: 1, service_item_id: 311101, name: 'document 1'}, {id: 2, service_item_id: 311102,, name: 'document 2'}, {id: 3, service_item_id: 311103,, name: 'document 3'}, {id: 4, service_item_id: 311104,, name: 'document 4'}]

He creado una función para crear el formulario

createControls(controls) {
    console.log(controls);
    for (let control of controls) {
        const newFormControl = new FormControl();
        this.myForm.addControl(control.service_item_id, newFormControl);
    }
}

this.createControls(this.documents);

Y en el Html he creado esto

<form [formGroup]="myForm" (ngSubmit)="submitForm()">
    <div *ngFor="let c of documentation; let index = index">
        <label>
            {{ c.name}}
        </label>
        <input type="number" [formControlName]="c.service_item_id" [placeholder]="c.name" />
        <button class="btn btn-primary btn-sm" (click)="add(c.service_item_id)">Add</button>
        <button class="btn btn-primary btn-sm" (click)="remove(c.service_item_id, index)">Remove</button>
    </div>
    <button type="submit" class="btn btn-primary btn-small">Submit</button>
</form>

Mis funciones de agregar y quitar son

add(item): void {
    (this.myForm.get(item) as FormArray).push(
      this.fb.control(null)
    );
  }

  remove(item, index) {
    (this.myForm.get(item) as FormArray).removeAt(index);
  }

Solo se está creando el formulario, pero los botones para agregar y eliminar no funcionan.

Por favor ayúdenme a resolver este problema. Gracias de antemano



------------------------------------

Creo que lo que funcionará mejor para su situación es utilizar FormArray. ConFormArray puede insertar y eliminar elementos tal como lo haría con una matriz normal

  myForm = this.fb.group({
    documents: this.fb.array([])
  });

  get documentsControl(): FormArray {
    return this.myForm.get("documents") as FormArray;
  }
  documents = [
    { id: 1, service_item_id: 311101, name: "document 1" },
    { id: 2, service_item_id: 311102, name: "document 2" },
    { id: 3, service_item_id: 311103, name: "document 3" },
    { id: 4, service_item_id: 311104, name: "document 4" }
  ];
  ngOnInit() {
    this.documents.forEach(document =>
      this.documentsControl.push(
        this.fb.group({
          id: [document.id],
          name: [document.name],
          service_item_id: [document.service_item_id]
        })
      )
    );
  }
  constructor(private fb: FormBuilder) {}
  submitForm() {}
  add() {
    this.documentsControl.push(
      this.fb.group({
        id: [null],
        name: [null],
        service_item_id: [null]
      })
    );
  }
  remove(index) {
    this.documentsControl.removeAt(index);
  }

para agregar elementos usamos push mientras que para eliminar elementos usamos removeAt

A continuación se muestra el html

<form [formGroup]="myForm" (ngSubmit)="submitForm()">
    <ng-container formArrayName='documents'>
      <div *ngFor="let c of documentsControl.controls; let index = index" [formGroupName]='index'>
        <label>
            {{ c.value.name}}
        </label>
        <input type="number" formControlName="service_item_id" placeholder="name" />
        <button class="btn btn-primary btn-sm" (click)="add()">Add</button>
        <button class="btn btn-primary btn-sm" (click)="remove(index)">Remove</button>
    </div>
    </ng-container>
    <button type="submit" class="btn btn-primary btn-small">Submit</button>
</form>
Editar

Para agregar elementos debajo del botón en el que se hizo clic, podemos implementar insert()

  insert(index) {
    const serviceItenId = this.documentsControl.controls[index].get('service_item_id').value
    this.documentsControl.insert(
      index + 1,
      this.fb.group({
        id: [null],
        name: [null],
        service_item_id: [serviceItenId]
      })
    );
  }

He actualizado la siguiente demostración para reflejar esto

Ver demostración

3

Gracias Owen, pero los campos de entrada se agregan al final de la página. ¿Hay alguna manera de agregarlo justo debajo del elemento en el que se hizo clic?

- Ex sitio

27 de marzo de 2021 a las 4:05

service_item_id viene como nulo, ¿hay alguna manera de replicarlo en la función de inserción? Gracias de antemano por tu ayuda

Ex-sitio

28/03/2021 a las 15:19

1

@Exsite ve la función de inserción actualizada()

-Owen Kelvin

28/03/2021 a las 15:57



------------------------------------

Creo que quieres hacer algo como

(this.myForm.controls as FormArray).push(this.fb.control(/*your item*/)

Y lo mismo para eliminar

Su guía para un futuro mejor - libreflare
Su guía para un futuro mejor - libreflare