I'm currently trying to implement a more plex version of the following behavior, but as I will not have access to my project until Monday, I'll simplify for the sake of it, using an altered example from Angular Material's tutorials.
An Angular Material table is filled with data from a string array. Data is presented in an input field on the first column. On the second column of every row is a set of buttons that, when pressed, change the contents of their line's input.
I've tried to identify the input element through the use of a template reference variable, but it always turns up as undefined. So I assume Angular Material's table is doing something behind my back that changes the scope of said variable.
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container matColumnDef="inputColumn">
<th mat-header-cell *matHeaderCellDef> No. </th>
<td mat-cell *matCellDef="let element">
<input #inputRef placeholder="{{element.name}}">
</td>
</ng-container>
<ng-container matColumnDef="buttonColumn">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element">
<button (click)="inputRef.value='Changed Element'">Change!</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
On my actual project, data will e from an API, and there will also be more buttons that will either enable the input, save or discard changes made to its content and so forth. But if I manage to get this example to work, then the remainder should be pretty straight forward.
Any help would be greatly appreciated.
I'm currently trying to implement a more plex version of the following behavior, but as I will not have access to my project until Monday, I'll simplify for the sake of it, using an altered example from Angular Material's tutorials.
An Angular Material table is filled with data from a string array. Data is presented in an input field on the first column. On the second column of every row is a set of buttons that, when pressed, change the contents of their line's input.
I've tried to identify the input element through the use of a template reference variable, but it always turns up as undefined. So I assume Angular Material's table is doing something behind my back that changes the scope of said variable.
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container matColumnDef="inputColumn">
<th mat-header-cell *matHeaderCellDef> No. </th>
<td mat-cell *matCellDef="let element">
<input #inputRef placeholder="{{element.name}}">
</td>
</ng-container>
<ng-container matColumnDef="buttonColumn">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element">
<button (click)="inputRef.value='Changed Element'">Change!</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
On my actual project, data will e from an API, and there will also be more buttons that will either enable the input, save or discard changes made to its content and so forth. But if I manage to get this example to work, then the remainder should be pretty straight forward.
Any help would be greatly appreciated.
Share Improve this question asked Jan 25, 2019 at 21:47 ChronusChronus 3013 silver badges17 bronze badges1 Answer
Reset to default 5You can solve this by using ViewChildren
to access all the input elements in your table and identifying them via the id
attribute for example.
Check out this stackblitz where I threw together a quick solution.
Basically all I did in the template was to add the matInput
directive to your input
elements and uniquely identify each one of the via the id
attribute (just assigning the inputColumn
variable of the current row element
):
<mat-form-field>
<input matInput id="{{element.inputColumn}}" placeholder="{{element.inputColumn}}">
</mat-form-field>
Added a function call on your button where we pass the current rows element
:
<button mat-raised-button (click)="changeValue(element)">{{element.buttonColumn}}</button>
In the ponent we retrieve all the input
elements with the matInput
directive:
@ViewChildren(MatInput) matInputs: QueryList<MatInput>;
And then in the function that gets called by the buttons we search for the correct matInput
via the id
that corresponds to the element
's inputColumn
value:
changeValue(element: TableData) {
const input = this.matInputs.find(matInput => matInput.id === element.inputColumn);
input.value = 'Changed!';
}
I am sure there are other ways to solve this, not sure how this behaves if you have a lot of buttons/rows.