Search code examples
angulartypescriptangular-formbuilder

dynamic form, dynamic added row is empty while submitting


Currently im working on a gender overview where you can edit genders, add or delete this with a simple table. Its already possible to add and delete rows. Currently im fighting with showing the correct web api data as a value in the textbox and getting all data from the form to post it back to the web api. My problem is that after i console.log the data of my updated datasource the new values are still empty. I will show it in a screenshot below.

This is my table:

<div class="controlpanel">
    <div id="operatoren">
        <button mat-mini-fab color="primary"(click)="addRow()" > <mat-icon color="white">  add </mat-icon> </button>
    </div>
</div>
<div class="container">
<form [formGroup]="genderForm">
    <table mat-table [dataSource]="genderDataSource" #genderTable >
        <ng-container matColumnDef="edit">
        <th mat-header-cell *matHeaderCellDef> Speichern  <mat-icon color="primary"> save </mat-icon> </th>
        <td mat-cell *matCellDef="let anreden; "> 
            
            <button mat-mini-fab color="primary" (click)="saveRow()" > <mat-icon color="white">  save </mat-icon> </button>
            
            </td>
        </ng-container>
        <ng-container matColumnDef="delete">
        <th mat-header-cell *matHeaderCellDef> Löschen <mat-icon color="warn"> clear </mat-icon> </th>
        <td mat-cell *matCellDef="let anreden; let i = index"> 
            <button mat-mini-fab color="warn" (click)="confirmDelete(anreden.bezeichnung,i)" > <mat-icon color="white">  clear </mat-icon> </button>
            </td>
        </ng-container>
        <ng-container matColumnDef="bezeichnung">
        <th mat-header-cell *matHeaderCellDef> Bezeichnung </th>
        <td mat-cell *matCellDef="let anreden; "> 
            <ng-container>
                <mat-form-field appearance="standard">
                    <input matInput type="text" [value]='anreden.bezeichnung' formControlName="bezeichnung" name="anreden"> 
                </mat-form-field>
            </ng-container>       
        </ng-container>
        <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
        <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
    </table>
    </form>
</div>

This is my ts to handle the table

  public displayedColumns = ['edit', 'delete', 'bezeichnung'];
  public genderDataSource: any[];
  public anreden = [] as any;
  genderForm: FormGroup;
  
  
  constructor(
    public dialog: MatDialog,
    public aService: AnredeVorschlägeService,
    private fb: FormBuilder,
  ) { 
  }
  createNewGender(): FormGroup{
    return this.fb.group({
      anredeVorschlagId: '',
      bezeichnung: new FormControl(''),
    })
  }
  @ViewChild('genderTable') table: MatTable<any>;
  ngOnInit(): void {
    this.genderForm = this.fb.group({
      anredeVorschlagId: '',
      bezeichnung: [''],
    });
    //Alle bezeichnungn
    this.aService.getAnrede()
    .subscribe(
      data => { 
        this.anreden = data;
        this.genderDataSource = data;
        console.log(this.genderDataSource);
        this.getStandardValues();
    });
  }
  addRow(){
      this.genderDataSource.push(this.createNewGender().value);
      this.table.renderRows();
  }
  saveRow(){

    console.log(this.genderForm.value);
    console.log(this.genderDataSource);
  }
  getStandardValues(){
    this.genderForm.patchValue({
      bezeichnung: this.anreden
    })
  }
  delRow(i:any){
    this.genderDataSource.splice(i, 1);
    this.table.renderRows();
  }
  confirmDelete(bezeichnung: string, i: any){
    this.dialog.open(ConfirmDialogComponent).afterClosed().subscribe(confirm => {
    if(confirm){
      this.delRow(i);
    }
    })
  }
}
Thats how it currently looks like: https://ibb.co/fXQ8mL8

The first and the second row should have the value "Herrn" and "Frau" coming from the web api, i dont know why they have "object Object". The third row is my dynamically added row. In my array with 3 entries should be "bezeichnung: 123" and not "bezeichnung: ''"(line 56). Just logging the form value otherwise works and returns the correct value(line 55).

My Service:

readonly aV = 'http://localhost:5000/api/anredevorschläge';
  getAnrede(): Observable<AnredeVorschläge[]> {
    return this.http.get<AnredeVorschläge[]>(this.aV);
  }


Solution

  • First of all it would be great if you could add some type information to your example.

    Second, I think your form structure has to be changed. Currently all your rows are connected with the genderForm instead of the form group you actually created for this row. Remove the genderForm and instead do the following to actually always work on the correct form control.

    <ng-container>
      <mat-form-field appearance="standard" [formGroup]=anrede.parent>
        <input matInput type="text" formControlName="bezeichnung"> 
      </mat-form-field>
    </ng-container>

    Third, it looks like the problem with [object object] in the form controls from the API comes from the AnredeVorschlägeService.getAnreden() function because you are directly assigning the result of this function to the data source. To solve this problem we would need the code of this function or the return type of the getAnreden() function.