Home > Back-end >  Dynamical adding checkbox to each row in table angular
Dynamical adding checkbox to each row in table angular

Time:12-12

enter image description here

In the above image i want to add checkbox and its label dynamical to each row when click on 'Add New checkbox' button.

so when i click on it button will visible a input box and type the checkbox name and submit the new checkbox will visible only in that particular row.

i think we can achieve through the form array but not getting the result.

example: adding a new checkbox in the ENMT row so i click add new button and input box visible and add a label 'Other' so a new checkbox called 'other' will appear on the row

enter image description herei am

expecting like this a new field on ENMT

CodePudding user response:

I spent a significant amount of time to figure it out for you.

First of all let's clean up your data model. Let's call each line a LineItem and each checkbox a Characteristic. I created for this appr. interfaces and created an array with sample data:

interface Characteristic {
  name: string;
  value: boolean;
}

export interface LineItem {
  label: string;
  characteristics: Characteristic[];
}

After that let's define the form:

form = this.fb.group({
    lineItems: this.fb.array([
      this.fb.group({
        label: '',
        characteristics: this.fb.array([
          this.fb.group({ name: '', value: false }),
        ]),
      }),
    ]),
  });

In this example I consider the whole table as a form and not the single rows.

The rows are the lineItems, which is a FormArray and it holds a FormGroup with controls like label and characteristics (which is a FormArray too, with the controls name and value).

Then I define a getter for easier access in the template:

get lineItems() {
    return this.form.get('lineItems') as FormArray;
  }

In the ngOnInit I fill up the form with the sample data:

ngOnInit() {
    const lineItems = <FormArray>this.form.get('lineItems');
    lineItems.clear();

    this.data.forEach((lineItem) => {
      let newLineItem = this.fb.group({
        label: '',
        characteristics: this.fb.array([]),
      });
      lineItems.push(newLineItem);
      lineItem.characteristics.forEach((char) => {
        let newChar = this.fb.group({ name: '', value: false });
        (<FormArray>newLineItem.get('characteristics')).push(newChar);
      });
    });

    this.form.setValue({ lineItems: this.data });
    console.log('initial form value: ', this.form.value);
  }

If we click on the appr. 'add new checkbox' button, I add the new checkbox with the name 'other' to the corresponding row:

onAddNewCheckbox(row: number) {
    const newChar = this.fb.group({ name: 'other', value: false });
    (<FormArray>this.lineItems.controls[row].get('characteristics')).push(
      newChar
    );
  }

Btw, you could use here some input dialog in order to get the name from the user.

After that we have to set up the template:

<form [formGroup]="form" (ngSubmit)="onSubmit()">
  <div formArrayName="lineItems">
    <table>
      <tr *ngFor="let lineItem of lineItems.controls; let row = index">
        <div style="display: flex" [formGroupName]="row">
          <td>{{ lineItem.get('label').value }}</td>
          <div style="display: flex" formArrayName="characteristics">
            <td
              *ngFor="
                let char of lineItem.get('characteristics').value;
                let column = index
              "
            >
              <div [formGroupName]="column">
                <input
                  type="checkbox"
                  id="{{ row }} - {{ column }}"
                  formControlName="value"
                />
                <label for="{{ row }} - {{ column }}">{{ char.name }}</label>
              </div>
            </td>
            <button (click)="onAddNewCheckbox(row)" type="button">
              add new checkbox
            </button>
          </div>
        </div>
      </tr>
    </table>
  </div>
  <button type="submit">submit</button>
</form>

I used a simple table element for this, but the logic should be similar for mat-table.

If you then click the checkboxes or add new ones and hit the submit button, you get a form value like this:

form value

Here you can find a working stackblitz example.

  • Related