Home > Back-end >  Angular mat-table with input fields and checkboxes
Angular mat-table with input fields and checkboxes

Time:08-26

I'm getting some data from backend and displaying it in my UI. The problem is I want to be able to modify each row's input field and checkbox and then submit the whole form and process the information.

I can render the page, no problem, but I have no clue where to start with creating the FormArray and how to place them in my HTML to be able to click on the save button and submit the entire form.

Here is my type script code

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { AttributeSetRootObject } from '../../models/attribute-set.model';
import { AttributeSetService } from '../../services/attribute-set.service';

@Component({
  selector: 'app-attribute-set-standard',
  templateUrl: './attribute-set-standard.component.html',
  styleUrls: ['./attribute-set-standard.component.scss'],
})
export class AttributeSetStandardComponent implements OnInit {
  attributeSets: AttributeSetRootObject;
  attributeSetForm: FormGroup;

  displayedColumns = [
    'attributeName',
    'englishLabel',
    'frenchLabel',
    'dataType',
    'fieldType',
    'defaultValue',
    'mandatoryIndicator',
  ];

  constructor(
    private route: ActivatedRoute,
    private attributeSetService: AttributeSetService,
    private fb: FormBuilder
  ) {}

  ngOnInit(): void {
    const attributeSetId = parseInt(this.route.snapshot.paramMap.get('id'));
    console.log(attributeSetId);

    this.attributeSetForm = this.fb.group({
      defaultValue: [],
      mandatory: [],
    });

    this.attributeSetService.getStandardAttributes(attributeSetId).subscribe({
      next: (data: AttributeSetRootObject) => {
        console.log(data);
        this.attributeSets = data;
      },
    });
  }

  onSubmit() {
    console.log(this.attributeSetForm.value);
  }
}

HTML Code

<app-breadcrumb [crumbs]="attributeSets?.data.parentlinks"></app-breadcrumb>

<div >
  <h3>{{ "ATTRIBUTE-SET.STANDARD-ATTRIBUTES-TITLE" | translate }}</h3>
  <div  *ngIf="attributeSets?.data?.attributes?.length">
    <form [formGroup]="attributeSetForm" (ngSubmit)="onSubmit()">
      <table
        mat-table
        #attributeSetSort="matSort"
        [dataSource]="attributeSets.data.attributes"
        matSort
        matSortDisableClear
      >
        <ng-container matColumnDef="attributeName">
          <th mat-header-cell *matHeaderCellDef mat-sort-header>
            Attribute Name
          </th>
          <td mat-cell *matCellDef="let element">
            {{ element.attributeName }}
          </td>
        </ng-container>

        <ng-container matColumnDef="englishLabel">
          <th mat-header-cell *matHeaderCellDef mat-sort-header>
            English Label
          </th>
          <td mat-cell *matCellDef="let element">
            {{ element.englishLabel }}
          </td>
        </ng-container>

        <ng-container matColumnDef="frenchLabel">
          <th mat-header-cell *matHeaderCellDef mat-sort-header>
            French Label
          </th>
          <td mat-cell *matCellDef="let element">
            {{ element.frenchLabel }}
          </td>
        </ng-container>

        <ng-container matColumnDef="dataType">
          <th mat-header-cell *matHeaderCellDef mat-sort-header>Data Type</th>
          <td mat-cell *matCellDef="let element">
            {{ element.dataType }}
          </td>
        </ng-container>

        <ng-container matColumnDef="fieldType">
          <th mat-header-cell *matHeaderCellDef mat-sort-header>Field Type</th>
          <td mat-cell *matCellDef="let element">
            {{ element.fieldType }}
          </td>
        </ng-container>

        <ng-container matColumnDef="defaultValue">
          <th mat-header-cell *matHeaderCellDef mat-sort-header>
            Default Value
          </th>
          <td mat-cell *matCellDef="let element">
            <mat-form-field>
              <mat-label 
                >{{ "ATTRIBUTE-SET.DEFAULT-VALUE" | translate }}
              </mat-label>
              <input
                type="text"
                matInput
                formControlName="defaultValue"
                [value]="element.defaultValue"
              />
            </mat-form-field>
          </td>
        </ng-container>

        <ng-container matColumnDef="mandatoryIndicator">
          <th mat-header-cell *matHeaderCellDef mat-sort-header>Mandatory</th>
          <td mat-cell *matCellDef="let element">
            <mat-checkbox
              formControlName="mandatory"
              [checked]="element.mandatoryIndicator === 'Y'"
            ></mat-checkbox>
          </td>
        </ng-container>

        <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
        <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
      </table>

      <button mat-raised-button color="primary">
        {{ "BUTTONS.SAVE" | translate }}
      </button>
    </form>
  </div>
</div>

The UI

This is how the page looks like

Right now when I click on save, it only submits one value. I would like to be able to submit all the values for the form.

CodePudding user response:

You can check the https://material.angular.io/components/table/overview link. They have sample forms with code. Try to read Angular Material Documentation too.

CodePudding user response:

When we work with a FormArray when not use in the "clasic way" we can simply use <input [formControl]="...">

To get the formControl we can use a function. e.g. you can use

  formArray:FormArray;
  getControl(index: number, controlName: string): FormControl {
    return (this.formArray.at(index) as FormGroup)
                .get(controlName) as FormControl;
  }

Now you can define your "cells" like

    <ng-container matColumnDef="defaultValue">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>
        Default Value
      </th>
      <td mat-cell *matCellDef="let element;let i = index">
          <input
            type="text"
            matInput
            [formControl]="getControl(i,'defaultValue')"
          />
      </td>
    </ng-container>

    <ng-container matColumnDef="mandatoryIndicator">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>Mandatory</th>
      <td mat-cell *matCellDef="let element;let i=index">
        <mat-checkbox
          [formControl]="getControl(i,'mandatory')"
        ></mat-checkbox>
      </td>
    </ng-container>

See that not use value in the check. You should create the formArray mapping the dataSource.data

formArray = new FormArray(
    this.attributeSets.data.attributes.map(
      (x:any) =>
        new FormGroup({
          defaultValue: new FormControl(x.defaultValue),
          mandatory: new FormControl(x.mandatory == 'yes' ? true : false),
        })
    )
  );

a stackblitz

  • Related