ngx-datatable - custom columns with action buttons
Solution 1
I am using the ngx-datatable
library, and I have a similar setup to your project, thus I believe I see where your problem is coming from.
If your <ng-template>
is not nested within the <ngx-datatable-column>
,you should put it within it. In addition, on your click
event binding, you should be passing the row
values into your onSelect()
methods, since you are trying to access the row data. You will need to use the ngx-datatable-cell-template
directive within your <ng-template>
too.
This are the changes you should be making:
<ngx-datatable
[rows]="rows"
class="material"
[loadingIndicator]="loadingIndicator"
[columnMode]="'force'"
[headerHeight]="50"
[footerHeight]="50"
[rowHeight]="'auto'"
[columns]="columns"
[reorderable]="reorderable">
<ngx-datatable-column *ngFor="let column of columns; let i = index;" name="{{column.name}}" prop="{{column.prop}}">
<ng-template let-value="value" let-row="row" *ngIf="column.name==='Actions'" ngx-datatable-cell-template>
<span>
<button style="background-color:red;height:15px;" (click)='onSelectRed(row)'><i class="rb-ic rb-ic-add-frame"></i></button>
<button style="background-color:blue;height:15px;" class="btn" (click)='onSelectBlue(value)'><i class="rb-ic rb-ic-add-frame"></i></button>
</span>
</ng-template>
</ngx-datatable-column>
</ngx-datatable>
And on your component.ts, you should be able to access the data of the entire row, or the value of the property itself, depending on the value you have binded on the click method.
onSelectRed(row) {
console.log(row);
}
onSelectBlue(value) {
console.log(value);
}
I have created a demo over here. As you can see, the values of row
and the binded property (id
) can be accessed within the row buttons itself.
Solution 2
<ng-container *ngFor='let column of columns' >
<ngx-datatable-column *ngIf='column.name === "Actions"' name="Actions" prop="actions">
<ng-template let-value="value" let-row="row" ngx-datatable-cell-template>
<span>
<button class='btn btn-icon icon-left'>
Continue
<i [ngClass]='row.actions.continue'></i>
</button>
<button class='btn btn-icon icon-left'>
Remove
<i [ngClass]='row.actions.delete'></i>
</button>
</span>
</ng-template>
</ngx-datatable-column>
<ngx-datatable-column *ngIf='column.name !== "Actions"' name="{{column.name}}" prop="{{column.prop}}">
</ngx-datatable-column>
</ng-container>
OP wentjun's solution works better with an ng-container in Angular 10+.
Solution 3
Credits to @m4limo
(I added my own observations)
Original comment
just use the ng-tamplate
:
<ngx-datatable-column name="Actions" sortable="false" prop="id">
<ng-template let-row="row" let-value="value" ngx-datatable-cell-template>
<button md-icon-button (click)="blockAgents(value)">
<i class="fa fa-ban"></i>
</button>
<button md-icon-button (click)="approveAgent(value)">
<i class="fa fa-check"></i>
</button>
</ng-template>
</ngx-datatable-column>
value
corresponds to the property prop
you define in ngx-datatable-column
, in this case id
Observations
You need to declare the column prop name inside the prop
property of the ngx-datatable-column
element, let-value
will assign the property to a variable, in this case, named "value", which will be assigned/used in your ng-template
child object.
"value" will get the property value from your row (object listed) using the column prop
value. The column prop name NEED to match with a property of the row object.
Notes
- Tested in Angular 9.1.1 (using Ivy)
- Using @swimlane/ngx-datatable 16.0.3
Original GitHub comment here
![Codehan25](https://i.stack.imgur.com/IybwQ.png?s=256&g=1)
Codehan25
Updated on July 09, 2022Comments
-
Codehan25 almost 2 years
I have a table (ngx-datatable) in which I want to define an "actions" column in which buttons will then be placed for CRUD operations.
Creating the column and placing the buttons worked, but I have the problem that the selected row and the values in its columns are no longer recognized inside my triggered function.
Here is my template:
<div class="col-12"> <ngx-datatable #table class="material" [rowHeight]="'auto'" [columns]="columns" [columnMode]="'force'" [headerHeight]="50" [footerHeight]="50" [limit]="10" [rows]="cars?.content" [selected]="selected" [selectionType]="'multi'"> </ngx-datatable> </div>
Here is my custom template with the buttons:
<ng-template #buttonsTemplate let-row="row" let-value="value" let-button="column.actions"> <button class="btn btn-transparent" (click)='onSelect($event)'><i class="rb-ic rb-ic-add-frame"></i></button> <button class="btn bt n-transparent" (click)='onSelect($event)><i class="rb-ic rb-ic-abort-frame"></i></button> <button class="btn btn-transparent" (click)='onSelect($event)><i class="rb-ic rb-ic-reset"></i></button> <button class="btn btn-transparent" (click)='onSelect($event)><i class="rb-ic rb-ic-agility"></i></button> </ng-template>
My component (.ts file) is structured like this:
export class MyComponent implements OnInit, OnDestroy { @ViewChild('buttonsTemplate') buttonsTemplate: TemplateRef<any>; columns = []; ngOnInit() { this.columns = [ {prop: 'id', name: 'Id'}, {prop: 'serial_number', name: 'Serial Number'}, {prop: 'actions', name: 'Actions', cellTemplate: this.buttonsTemplate} ]; } // This method should be called after clicking an action button onSelect({selected}) { console.log('Array of selected vehicles', selected); } }
Currently this error occurs in the console:
ERROR TypeError: Cannot read property 'serial_number' of undefined
What am I doing wrong? The official documentation and demo page doesn't helped me..
Approach from @wentjun (not working: button not visibile inside column)
The Template:
<ngx-datatable-column *ngFor="let column of columns; let i = index;" name="{{column.name}}" prop="{{column.prop}}"> <ng-template #buttonsTemplate let-row="row" let-value="value" ngx-datatable-cell-template> <button class="btn btn-transparent" (click)='onSelect(row)'><i class="rb-ic rb-ic-add-frame"></i></button> </ng-template> </ngx-datatable-column>
The Component (function):
onSelect({selected}) { console.log('Array of selected vehicles', selected); }
-
Codehan25 about 5 yearsI've updated my question with your approach. Now the buttons are no longer visible inside the columns..
-
wentjun about 5 yearsHi, I must apologise, for I wasn't very clear with my explanation. I have created a demo, and added more details in the code on my answer. Hope it clears things up for you.
-
Abhishek Soni about 4 yearsI have copied your code exactly line by line, I thought it may be some mistakes, but not worked for me. I don't know how, exact same is working when I modify your slackblitz code. Please point me to some link, I am not able to perform crud operation in my application.