1

I am trying to do something that seems like it should be simple,but I obviously do not understand something.

We have a custom document object, it relates to another custom object. I have a datatable listing the documents on the record page of the custom object it relates to.

The last column has a download icon, I don't want to display any data there just the icon (the 'xxx' in the JS is just testing so there is a value there).

When I say download that is going to be done from a remote service and I have code that will do it, I just need to get the value from this row and pass it to the download code. For whatever reason I can get the data to the onclick function.

I have tried using target. a wide variety of fields, and event. a wide variety of fields. Everything comes back 'undefined' except if I put event.detail (with nothing further) then it always evaluates as the value '1', no matter which row I am clicking on.

I obviously don't understand the most basic parts of passing a value from the table back to the controller, would anyone care to help out?

HTML:

<template>
<lightning-card title="File List">

    <lightning-datatable data={documents} columns={columns} key-field="Id" onclick={handleClick}></lightning-datatable>
</lightning-card>

Javascript:

export default class TestLWC extends LightningElement {
@track columns = [
    {
        label: 'File Name',
        fieldName: 'nameUrl',
        type: 'url',
        typeAttributes: {label: { fieldName: 'Name' },
        target: '_blank'},
        sortable: true
    },
    {
        label: 'File Type',
        fieldName: 'File_Type__c',
        type: 'text',
        sortable: true
    },
    {
        label: 'Related To',
        fieldName: 'relatedTo',
        type: 'url',
        typeAttributes: {label: { fieldName: 'Related_To__c' },
        target: '_blank'},
        sortable: true
    },
    {
        fieldName: 'test',
        label: 'Download',
        cellAttributes: { iconName: 'action:download', onClick: 'handleDownloadClick' }
    }

];
@api recordId;
@track error;
@track documents = [];

handleClick(event) {
    const displayStr = event.detail;
    //I have also tried target here
    alert('hello '+displayStr);

}
//@wire(getAllDocs)
@wire(getRelatedDocs,{recordId: '$recordId'})
wiredDocs(result) {
    const { data, error } = result;
    // eslint-disable-next-line no-console
    console.log('SCH data '+result);
    if(data) {
        let nameUrl;
        let relatedTo;
        let test;
        this.documents = data.map(row => {
            nameUrl = `${row.File_Link__c}`;
            relatedTo = `/${row.Related_To__c}`;
            test='xxx';
            return {...row ,nameUrl,relatedTo,test}
        })
        this.error = null;
    }
    if(error) {
        this.error = error;
        this.opportunities = [];
    }
}

}

1

You can still use the actions type with a button icon and without the drop down menu. For this, you need to add onrowaction attribute to the lightning-datatable.

Then once you click on the button icon, the function handleRowAction will be invoked based on the action name and event.detail.row captures which row triggered the button click event.

The sample code below is a tweaked version of the example from the LWC guide : Data table with row actions

Playground version

withRowActions.html

<template>
    <div style="height: 300px;">
        <lightning-datatable
                key-field="id"
                data={data}
                columns={columns}
                onrowaction={handleRowAction}>
        </lightning-datatable>
    </div>
    <div class="slds-m-around--medium" style="width: 30rem;">
        <article class="slds-tile">
            <h3 class="slds-tile__title slds-truncate" title="Record details"><a href="javascript:void(0);">Record details</a></h3>
            <div class="slds-tile__detail">
                <dl class="slds-list_horizontal slds-wrap">
                    <dt class="slds-item_label slds-text-color_weak slds-truncate" title="Name">Name:</dt>
                    <dd class="slds-item_detail slds-truncate">{record.name}</dd>
                    <dt class="slds-item_label slds-text-color_weak slds-truncate" title="Balance">Balance:</dt>
                    <dd class="slds-item_detail slds-truncate">
                        <lightning-formatted-number value={record.amount} format-style="currency"></lightning-formatted-number>
                    </dd>
                </dl>
            </div>
        </article>
    </div>
</template>

withRowActions.js

import { LightningElement, track } from 'lwc';
import fetchDataHelper from './fetchDataHelper';

const actions = [
    { label: 'Download', name: 'download' }
];

const columns = [
    { label: 'Name', fieldName: 'name' },
    { label: 'Website', fieldName: 'website', type: 'url' },
    { label: 'Phone', fieldName: 'phone', type: 'phone' },
    { label: 'Balance', fieldName: 'amount', type: 'currency' },
    { label: 'Close At', fieldName: 'closeAt', type: 'date' },
    {type: 'button-icon', typeAttributes: {  
        iconName: 'utility:download',
        label: 'Download',  
        name: 'download',  
        variant: 'bare',
        alternativeText: 'download',        
        disabled: false
    }}
];

export default class DatatableWithRowActions extends LightningElement {
    @track data = [];
    @track columns = columns;
    @track record = {};

    async connectedCallback() {
        this.data = await fetchDataHelper({ amountOfRecords: 100 });
    }

    handleRowAction(event) {
        const actionName = event.detail.action.name;
        const row = event.detail.row;
        switch (actionName) {
            case 'download':
                this.showRowDetails(row);
                break;                      
            default:
        }
    }

    showRowDetails(row) {
        this.record = row;
        console.log(JSON.stringify(row));
        console.log(JSON.stringify(row.name));
    }

}

fetchDataHelper.js (used only display sample data in the table)

const recordMetadata = {
    name: 'name',
    email: 'email',
    website: 'url',
    amount: 'currency',
    phone: 'phoneNumber',
    closeAt: 'dateInFuture',
};

export default function fetchDataHelper({ amountOfRecords }) {
    return fetch('https://data-faker.herokuapp.com/collection', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json; charset=utf-8',
        },
        body: JSON.stringify({
            amountOfRecords,
            recordMetadata,
        }),
    }).then(response => response.json());
}
2
  • Chosen as answer. Thank you so much Shamina for such a complete and detailed explanation! – ScottH7a9 Feb 3 '20 at 14:27
  • @ScottH7a9 Glad I could help :) – Shamina Feb 3 '20 at 14:32
0

If you are willing you use the "actions" type for your cell and provide it with the button and it's features. The drawback is that it is inside a dropdown and not just a button in the cell.

If you are 100% set on having a custom button in the cell that does what you need you can specify custom types for datatables that will allow you to achieve your requirement. Have a look at the following documentation: Lightning Datatable

Scroll down to the section labelled "Creating Custom Data Types", this is how I managed to do it.

2
  • Thanks for the answer. This is a pretty simple component, I would be willing to change it slightly, I'm not sure if I want the level of effort to create a custom data type. I think I will go with the button idea. Do you know where I could find an example of how it works? The issue I am having is how to get the value of the id for the row when the button is clicked? – ScottH7a9 Feb 1 '20 at 12:20
  • The answer and example provided by @Shamina is definitely a winner! – Adrian van Wyk Feb 1 '20 at 18:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.