Using Angular material MatTableDataSource in combination with FormArray

Posted on Sept. 22, 2018
formbuilder
matTable
formarray
Formgroup
dynamic forms
24031

Expected Behaviour: When user clicks on add data, table with empty column need to be displayed and want form control for newly added data.

 

For this behaviour, I used MatTableDataSource class and FormArray class and MatTable.

MatDataSource is a material class which accepts client side data array and includes native support of filtering, pagination

and sorting.  Data source provides stream, it bears the responsibility of triggering table updates.

FormArray is an alternative to FormGroup for managing any number of unnamed controls.

The mat-table provides a Material Design styled data-table that can be used to display rows of data.

I defined passengerData Array as type of PassengerDetails and used this array as data source for mat table.

 

This is the structure of PassengerDetails interface. 

export interface PassengerDetails {
Gender: string;
Name : string;
Age: string;
SeatNo: string;
}
 

 

And passengerData array.  

passengerData:PassengerDetails[]=[];

 

Declare formBuilder and formGroup.

passengerForm: FormGroup;
private fb: FormBuilder;

 

Use formArray and formGroup to bind formcontrols(I also have other inputs like pPname, pEmail, pPhone)

//Passenger List Form
this.passengerForm= this.fb.group({
pPName: ['',Validators.required],
pEmail: ['',[Validators.required, Validators.email]],
pPhone: ['',[Validators.required, Validators.maxLength(10),Validators.minLength(10),Validators.pattern('[0-9]+')]],
passengerArray: this.fb.array([])
});
}
 
get passengerArray(){
return this.passengerForm.get('passengerArray') as FormArray;
}
 

 

Define columns array that needs to be rendered in mat table. 

cols:string[] = ["Gender", "Name", "Age", "Seat No"];

 

To bind the data in passengerData to Mat-table, use datasource property in html mat-table. However, I want to frequently update table data and those changes should be reflected in html. So, I am passing updated passengerData array to MatTableDataSource.

When user clicks on add button, an empty passengerDetails object will be created in passengerData array.

datasource = new MatTableDataSource(this.passengerData);
this.passengerArray.push(this.fb.group({
Gender:'',
Name:'',
Age:'',
Seat:seat.seatNo
}));
this.passengerData.push({Name: "",Age: "", Gender: "", SeatNo: seat.seatNo.toString()});
this.datasource = new MatTableDataSource(this.passengerData);

 

Below is the html code to render material table.  Here, in nth index (i.e. formGroupName) of passengerArray I have Gender, Name, Age and Seat parameters.

<ng-container formArrayName="passengerArray" >
<mat-table #table class="table table-bordered table-sm" [dataSource]="datasource">
<mat-header-row *matHeaderRowDef="cols"></mat-header-row>
<mat-row *matRowDef="let row; columns: cols;"></mat-row>
<ng-container matColumnDef="Gender">
<mat-header-cell *matHeaderCellDef> Gender </mat-header-cell>
<mat-cell *matCellDef="let element; let index = index" [formGroupName]="index" >
<mat-form-field style="width: 100px;">
<mat-select placeholder="Gender" formControlName="Gender" required>
<mat-option value="male">Male</mat-option>
<mat-option value="female">Female</mat-option>
</mat-select>
</mat-form-field>
</mat-cell>
</ng-container>
<ng-container matColumnDef="Name">
<mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
<mat-cell *matCellDef="let element; let index = index" [formGroupName]="index">
<mat-form-field style="width: 100px;">
<input matInput placeholder="Name" type="text" formControlName="Name" required>
</mat-form-field>
</mat-cell>
</ng-container>   
<ng-container matColumnDef="Age">
<mat-header-cell *matHeaderCellDef> Age </mat-header-cell>
<mat-cell *matCellDef="let element; let index = index" [formGroupName]="index">
<mat-form-field style="width: 100px;">
<input matInput placeholder="Age" type="text" formControlName="Age" required>
</mat-form-field>
</mat-cell >
</ng-container>
<ng-container matColumnDef="Seat No">
<mat-header-cell *matHeaderCellDef> Seat No </mat-header-cell>
<mat-cell *matCellDef="let element; let index = index">
<mat-label >{{element.SeatNo}}</mat-label>
</mat-cell>
</ng-container>   
</mat-table>
</ng-container>

 




2 comments

md
md

Hi
Can I have the link to get working code for this please? Like Github ...?

Greetings,
Aziz

abhi
abhi

Hi Aziz, Here is the link for your ref
https://github.com/abhi720/Angular

Please log in to leave a comment.