It's possible to have actions for each row in a data table that change depending on the contents of the rows (that are changed by those very actions). For example:
The component reference provides the following example code (activate/deactivate contacts):
Controller
({
init: function (cmp, event, helper) {
var actions = helper.getRowActions.bind(this, cmp);
cmp.set('v.mycolumns', [
// Other column data here
{ label: 'State', fieldName: 'active', type: 'text' },
{ type: 'action', typeAttributes: { rowActions: actions } }
]);
// Fetch or set your data
},
handleRowAction: function (cmp, event, helper) {
var action = event.getParam('action');
var row = event.getParam('row');
switch (action.name) {
case 'activate':
helper.activateContact(cmp, row)
break;
case 'deactivate':
helper.deactivateContact(cmp, row)
break;
}
}
})
Helper
({
getRowActions: function (cmp, row, doneCallback) {
var actions = [];
if (row['isActive']) {
actions.push({
'label': 'Deactivate',
'iconName': 'utility:block_visitor',
'name': 'deactivate'
});
} else {
actions.push({
'label': 'Activate',
'iconName': 'utility:adduser',
'name': 'activate'
});
}
// simulate a trip to the server
setTimeout($A.getCallback(function () {
doneCallback(actions);
}), 200);
},
activateContact: function (cmp, row) {
var rows = cmp.get('v.data');
var rowIndex = rows.indexOf(row);
rows[rowIndex]['isActive'] = true;
rows[rowIndex]['active'] = 'Active';
cmp.set('v.data', rows);
},
deactivateContact: function (cmp, row) {
var rows = cmp.get('v.data');
var rowIndex = rows.indexOf(row);
rows[rowIndex]['isActive'] = false;
rows[rowIndex]['active'] = 'Inactive';
cmp.set('v.data', rows);
}
})
Of special note is this line in the reference's explanation, right before the code:
When you click the dropdown menu, an asynchronous call is made to determine which actions to display for the particular row.
It also says, the logic that determines which action to display can be created on initialization, but doesn't indicate how. This is probably the key to a solution.
I'm pretty sure that's the root of the reason my attempt hasn't worked yet, as my version is not using action drop downs.
I'm trying to do something similar, only with button icons. I was tasked with attempting to replicate, via a lightning:datatable, what was previously accomplished in a component with HTML:
When you click a utility:add buttonIcon, it gets replaced with utility:check; the prevous utility:check is replaced with a utility:add. Utility:add does other things on the back end, but I'm only interested in the UI change.
I tried following the reference's pattern, but I haven't been successful yet. However, I'm hoping I'm on the right track. The button icons are blank when the page loads and nothing happens when I click them. Below is my code so far:
Controller
init : function(component, event, helper) {
var icon = helper.getIcon.bind(this, component);
component.set('v.caseColumns', [
{type: 'button-icon', typeAttributes: {name: 'addToCase', iconName: icon, alternativeText: 'Add the Pet to the Case'}},
{label: 'Pet Name', fieldName: 'linkName', type: 'url', typeAttributes: {label: { fieldName: 'Name' }, target: '_blank'}},
{label: 'Type', fieldName: 'Type__c', type: 'text'},
{label: 'Breed', fieldName: 'Breed__c', type: 'text'},
{label: 'Age', fieldName: 'Age__c', type: 'number'},
{label: 'Active', fieldName: 'Active__c', type: 'boolean'}
]);
helper.runInitProcess(component);
},
handleRowAction : function(component, event, helper) {
var rowAction = event.getParam('action');
var row = event.getParam('row');
switch (rowAction.iconName) {
case 'utility:check':
break;
case 'utility:add':
helper.addToCase(component, row)
break;
}
},
Helper
getIcon : function (component, row, doneCallback) {
var icon = '';
if (row['Selected_Pet__c']) {
icon = 'utility:check';
} else {
icon = 'utility:add';
}
// simulate a trip to the server
setTimeout($A.getCallback(function () {
doneCallback(actions);
}), 200);
},
addToCase : function (component, row) {
var rows = component.get('v.petList');
var rowIndex = rows.indexOf(row);
//Server Action
rows[rowIndex]['Selected_Pet__c'] = true;
component.set('v.petList', rows);
},
One last clue, the getIcon
function doesn't run at all. As a matter of fact, referring to the reference code once again, the comparable getRowActions
function only seems to run when you click an action drop down, consistent with the piece of explanation I highlighted earlier.