Angular FormArray: Removing Selected Items Leaves Undefined Values

39 Views Asked by At

I'm encountering an issue with an Angular application where I have a FormArray representing a list of selected items. When I select items from a list and then deselect them, undefined values are left in the FormArray.

I've implemented a toggle function that should add or remove items from the FormArray, and it mostly works, but when I remove an item, it's not properly cleaned up, and I end up with undefined values in the array.

Here's a simplified version of the relevant code:

My .ts file

export class LlamadoComponent {
 form: FormGroup;
  tipos: GenericData[] = [];
  lugares: GenericData[] = [];
  fuentes: GenericData[] = []



  constructor(private fb: FormBuilder, private placeService: CrudService) { //instancia el formulario
    //I get tipos from my service
    this.placeService.getTipos().subscribe(
      (tipos: GenericData[]) => {
        this.tipos = tipos;
      },
      (error: any) => {
        console.error('Error al obtener la lista de tipos:', error);
      }
    );

    this.placeService.getLugares().subscribe(
      (lugares: GenericData[]) => {
        this.lugares = lugares;
      },
      (error: any) => {
        console.error('Error al obtener la lista de tipos:', error);
      }
    );
    this.placeService.getFuente().subscribe(
      (fuentes: any[]) => {
        this.fuentes = fuentes;
      },
      (error: any) => {
        console.error('Error al obtener la lista de tipos:', error);
      }
    );



    // Init FormGroup here
    this.form = new FormGroup({
      nroLicitacion: new FormControl(''),
      extracto: new FormControl(''),
      nombreLicitacion: new FormControl(''),
      tipoLicitacion: new FormControl(''),
      fecha: new FormControl(''),
      hora: new FormControl(''),
      lugar: new FormControl(''),
      presupuesto: new FormControl(''),
      plazo: new FormControl(''),
      financiamiento: this.fb.array([]),
      operatoria: new FormControl(''),
      porLotes: new FormControl(''),
      gdeba1: new FormControl(''),
      gdeba2: new FormControl(''),
      gdeba3: new FormControl(''),
      gdeba4: new FormControl(''),
      // falta partidos seleccionados, ver estructura  
      lugarConsulta: new FormControl(''),
      lugarAdquisicion: new FormControl(''),
    });

    

  }



  get financiamientoArray(): FormArray {
    return this.form.get('financiamiento') as FormArray;
  }

  toggleFinanciamiento(id: number): void {
    const index = this.financiamientoArray.controls.findIndex(
      (control: AbstractControl<any, any>) => control.value === id
    );

    if (index !== -1) {
      // Si ya está seleccionado, deselecciónalo y elimina el control
      this.financiamientoArray.removeAt(index);
    } else {
      // Si no está seleccionado, agrégalo como nuevo control
      this.financiamientoArray.push(new FormControl(id));
    }

    // Actualiza el valor del FormArray con los valores actuales
    this.form.get('financiamiento')?.setValue(this.financiamientoArray.value);
  }`

And this is the html where I´m building my multiple select check
<h3 class="panel-title">Financiamiento</h3>
              <div class="checkbox-financiamiento">
                <mat-form-field>
                  <mat-label>Financiamiento</mat-label>
                  <mat-select multiple>
                    <mat-option *ngFor="let fuente of fuentes" [value]="fuente.id" (click)="toggleFinanciamiento(fuente.id)">
                      {{ fuente.descripcion }}
                    </mat-option>
                  </mat-select>
                </mat-form-field>
              </div>

CHATGPT suggested me the function toggleFinanciamiento but I´m still having undefined value problem

1

There are 1 best solutions below

0
Hamza Abbas On BEST ANSWER

You should use formArray.controls.remove or push https://blog.angular-university.io/angular-form-array/

toggleFinanciamiento(id: number): void {
const index = this.financiamientoArray.controls.findIndex(
  (control: AbstractControl<any, any>) => control.value === id
);

if (index !== -1) {
  // Si ya está seleccionado, deselecciónalo y elimina el control
  this.financiamientoArray.controls.removeAt(index);
} else {
  // Si no está seleccionado, agrégalo como nuevo control
  this.financiamientoArray.controls.push(new FormControl(id));
}

// Actualiza el valor del FormArray con los valores actuales
this.form.get('financiamiento')?.setValue(this.financiamientoArray.value);

}`