How to Add Hyperlink and icons in Lightning:datatable

on

|

views

and

comments

Hey Everyone,

Welcome again. In this blog post, we are going to learn how we can add hyperlink in datatable and how to add custom icons based on some conditions in lightning datatable

Use Case: –

Business wants to display the list of top 10 cases in a datatable. There are few catches here that are given below

  1. CaseNumber & Subject Field must be hyperlink and when click on those it should redirect to case detail page.
  2. Contact Name & Account Name field also should be hyperlink field and clicking on it should redirect to contact or account record.
  3. An icon should be displayed left to priority field and icon should be changed based on priority.

Now, as we have got the use case. Let’s see what all it will take to develop.

  1. An Apex class
  2. Lightning Web Component

Before we directly jump into the final outcome, we will break the requirement into multiple steps. So, let’s create the apex class first.

Use below code and Name it as CaseLWCService

public with sharing class CaseLWCService {
    @AuraEnabled
    public static List<Case> fetchCases(){
        return [SELECT Id, CaseNumber, Subject, Description, AccountId, Account.Name, ContactId,
        Contact.Name, Status, Priority 
        FROM CASE
        LIMIT 10];
    }
}

We have got our apex class which will return the Top10 Case records.

Now, let’s develop the component which will be using Lightning:datatable for displaying the records. Use below code for .html file

<template>
    <lightning-card  variant="Narrow"  title="Case List" icon-name="standard:case">
        <div class="slds-m-around_small">
            <lightning-datatable
                key-field="id"
                data={result}
                show-row-number-column
                hide-checkbox-column
                columns={columnsList}
                onrowaction={handleRowAction}>
            </lightning-datatable>
        </div>
    </lightning-card>
</template>

We have got the UI part, however we need to have the associated JavaScript class so that we can pull the data from Apex Class and that data can be displayed into component. Below is the code for the JS Class.

import { LightningElement, wire, api, track } from 'lwc';
import fetchCases from '@salesforce/apex/CaseLWCService.fetchCases';

const columns = [
    { label: 'CaseNumber', fieldName: 'CaseNumber' },
    { label: 'Subject', fieldName: 'Subject', wrapText: true},
    { label: 'Status', fieldName: 'Status' },
    { label: 'Priority', fieldName: 'Priority' },
    { label: 'Contact', fieldName: 'ContactName', wrapText: true },
    { label: 'Account', fieldName: 'AccountName', wrapText: true }
];
export default class CaseDatatable extends LightningElement {
    
    @api result;
    @track error;

    columnsList = columns;
    
    connectedCallback(){
        this.getAllCaseDetails();
    }

    getAllCaseDetails(){
        fetchCases()
            .then(data => {
                /* Iterate with Each record and check if the Case is Associated with Account or Contact
                    then get the Name and display into datatable
                */
                data.forEach(caseRec => {
                    if(caseRec.ContactId){
                        caseRec.ContactName = caseRec.Contact.Name;
                    }
                    if(caseRec.AccountId){
                        caseRec.AccountName = caseRec.Account.Name;
                    }
                });
                this.result = data;
                window.console.log(' data ', data);
                this.error = undefined;
            })
            .catch(error => {
                this.error = error;
                window.console.log(' error ', error);
                this.result = undefined;
            });
    }
    
    handleRowAction(){
        
    }
}

and below is the code for meta file

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>48.0</apiVersion>
    <isExposed>true</isExposed>
    <masterLabel>Case Details</masterLabel>
    <targets>
        <target>lightning__RecordPage</target>
        <target>lightning__AppPage</target>
        <target>lightning__HomePage</target>
        <target>lightningCommunity__Page</target>
        <target>lightningCommunity__Default</target>
    </targets>
</LightningComponentBundle>

We have developed the component and displayed the case list into datatable. However, we are still remaining with few point. If you will see the output of the above component will look like below

If you notice the above screenshot, there is no hyperlink shown for any of the fields which were mentioned in the use case.

Let’s modify the columns of datatable to display the link.

We are going to use same column which is CaseNumber and Subject. To display the url what we need to do is specify the type for the column like below

{ label: 'CaseNumber', fieldName: 'CaseNumber', type:'url' },

However, doing this will not work. What we need to do is to add some attributes in the same column under typeAttributes so that we can specify the text which we wanted to display. See code below, inside typeAttributes we can specify the target as well and many more. Learn Here

typeAttributes: {
           label: { fieldName: 'CaseNumber' },
           target : '_blank'
       }

Now, if we merge the code it will look like below

{ 
        label: 'CaseNumber', fieldName: 'CaseNumber', type:'url',
        typeAttributes: {
            label: { 
                fieldName: 'CaseNumber' 
            },
            target : '_blank'
        }
    },

We have prepared the column and there is one more thing remaining which is the actual URL. As if you noticed on the above code we are using CaseNumber in both places and the record details url look like below

https://+host+/+recordId

So, we have to prepare the URL and a new field so that we can use that new field in place of CaseNumber in the first place of fieldName: ‘CaseNumber’, type:’url’,

We will follow the same approach for the rest 3 fields ( Subject, Contact Name & Account Name). That means we will be needing 3 New fields which will contain the record detail page Link.

Now, here is the update code for JavaScript Class with URL/HyperLink in Datatable

import { LightningElement, wire, api, track } from 'lwc';
import fetchCases from '@salesforce/apex/CaseLWCService.fetchCases';

const columns = [
    { 
        label: 'CaseNumber', fieldName: 'caseUrl', type:'url',
        typeAttributes: {
            label: { 
                fieldName: 'CaseNumber' 
            },
            target : '_blank'
        }
    },
    { 
        label: 'Subject', fieldName: 'caseUrl', wrapText: true,
        type: 'url',
        typeAttributes: {
            label: { 
                fieldName: 'Subject' 
            },
            target : '_blank'
        }
    },
    { label: 'Status', fieldName: 'Status' },
    { label: 'Priority', fieldName: 'Priority' },
    { 
        label: 'Contact', fieldName: 'ContactUrl', wrapText: true,
        type: 'url',
        typeAttributes: {
            label: { 
                fieldName: 'ContactName' 
            },
            target : '_blank'
        } 
    },
    { 
        label: 'Account', fieldName: 'AccountUrl', wrapText: true,
        type: 'url',
        typeAttributes: {
            label: { 
                fieldName: 'AccountName' 
            },
            target : '_blank'
        } 
    }
];
export default class CaseDatatable extends LightningElement {
    
    @api result;
    @track error;

    columnsList = columns;
    
    connectedCallback(){
        this.getAllCaseDetails();
    }

    getAllCaseDetails(){
        fetchCases()
            .then(data => {
                /* Iterate with Each record and check if the Case is Associated with Account or Contact
                    then get the Name and display into datatable
                */
                /* Prepare the Org Host */
                let baseUrl = 'https://'+location.host+'/';
                data.forEach(caseRec => {
                    caseRec.caseUrl = baseUrl+caseRec.Id;
                    if(caseRec.ContactId){
                        caseRec.ContactName = caseRec.Contact.Name;
                        /* Prepare Contact Detail Page Url */
                        caseRec.ContactUrl = baseUrl+caseRec.ContactId;
                    }
                    if(caseRec.AccountId){
                        caseRec.AccountName = caseRec.Account.Name;
                        /* Prepare Account Detail Page Url */
                        caseRec.AccountUrl = baseUrl+caseRec.AccountId;
                    }
                });
                this.result = data;
                window.console.log(' data ', data);
                this.error = undefined;
            })
            .catch(error => {
                this.error = error;
                window.console.log(' error ', error);
                this.result = undefined;
            });
    }
    
    handleRowAction(){
        
    }
}

If you will preview the code, you will see the screen like below

We are done with 75% of the requirement however still we need to display the icons next to Priority based on priority. For this, we need to use cellAttributes property of the datatable column instead of typeattributes.

Let;s see how to display the icon and we can get the icons from here

{
        label: 'Priority', fieldName: 'Priority',
        cellAttributes: { 
            iconName: 'utility:sentiment_negative', 
            iconAlternativeText: 'Priority' 
        }
    },

If you have noticed, we are using icon name which is static and will display the same icon. So to display the icon dynamically we need to generate the icon in JS and use like below

{
        label: 'Priority', fieldName: 'Priority',
        cellAttributes:{ 
            iconName: { 
                fieldName: 'priorityIcon' 
            },
            iconPosition: 'left', 
            iconAlternativeText: 'Priority Icon' 
        }
    },

Below is the complete code for the blog

If you will preview the code you will see the output like below

Thanks for Reading. Sharing is Caring 🙂

If you have any questions or suggestions, please feel free to reach out to me.

Amit Singh
Amit Singhhttps://www.pantherschools.com/
Amit Singh aka @sfdcpanther/pantherschools, a Salesforce Technical Architect, Consultant with over 8+ years of experience in Salesforce technology. 21x Certified. Blogger, Speaker, and Instructor. DevSecOps Champion
Share this

Leave a review

Excellent

SUBSCRIBE-US

Book a 1:1 Call

Must-read

How to Utilize Salesforce CLI sf (v2)

The Salesforce CLI is not just a tool; it’s the cornerstone of development on the Salesforce Platform. It’s your go-to for building, testing, deploying, and more. As one of the most important development tools in our ecosystem

Save the day of a Developer with Apex Log Analyzer

Table of Contents What is Apex Log Analyzer? Apex Log Analyzer, a tool designed with Salesforce developers in mind, is here to simplify and accelerate your...

Salesforce PodCast

Introduction Hey Everyone, Welcome to my podcast, the first-ever podcast in India for Salesforce professionals. Achievement We are happy to announce that we have been selected as Top...

Recent articles

More like this

32 COMMENTS

  1. Hello Team,

    Thank you for nice blog. I learnt something out of it. I tried to modify for Account sObject but once i add to Builder I am not able to see records, can you please where I am missing:

    Class Logic:

    @AuraEnabled(cacheable=true)
    public static List getAccountList(){
    return [select id, Name, AccountNumber, Phone, Rating from Account
    LIMIT 5];
    }

    JS file:

    import { LightningElement, api, track } from ‘lwc’;
    import getAccountList from ‘@salesforce/apex/AccountController.getAccountList’;
    import ACCOUNTNUMBER_FIELD from ‘@salesforce/schema/Account.AccountNumber’;
    import PHONE_FIELD from ‘@salesforce/schema/Account.Phone’;
    import RATING_FIELD from ‘@salesforce/schema/Account.Rating’;
    const COLUMNS = [

    { label: 'Account', fieldName: 'AccountUrl', wrapText: true,
    type: 'url',
    typeAttributes: {
    label: {
    fieldName: 'AccountName'
    },
    target : '_blank'
    }
    },
    { label: 'Account Number', fieldName: ACCOUNTNUMBER_FIELD.fieldApiName, type: 'text' },
    { label: 'Phone', fieldName: PHONE_FIELD.fieldApiName, type: 'Phone' },
    { label: 'Rating', fieldName: RATING_FIELD.fieldApiName, type: 'Picklist' }

    ];

    export default class retrieveRecord extends LightningElement() {
    @api result;
    @track error;

    columnsList = COLUMNS;

    connectedCallback(){
    this.getAllCaseDetails();
    }

    getAllCaseDetails(){
    getAccountList()
    .then(data => {
    /* Iterate with Each record and check if the Case is Associated with Account or Contact
    then get the Name and display into datatable
    */
    /* Prepare the Org Host */
    let baseUrl = 'https://'+location.host+'/';

    data.forEach(accRec => {
    accRec.AccountUrl = baseUrl+accRec.Id;

    if(accRec.Id){
    accRec.AccountName = accRec.AccountName;
    /* Prepare Account Detail Page Url */
    accRec.AccountUrl = baseUrl+accRec.Id;
    }

    });
    this.result = data;
    window.console.log(' data ', data);
    this.error = undefined;
    })
    .catch(error => {
    this.error = error;
    window.console.log(' error ', error);
    this.result = undefined;
    });
    }

    handleRowAction(){

    }

    }

    HTML:

    meta.xml:

    49.0
    true

    lightning__AppPage
    lightning__RecordPage
    lightning__HomePage

    Please advise what went wrong and how to correct at the earliest.

    Regards,
    HS

  2. Hello there,

    in conjunction to my initial post, I have printed the error log in console and got below stacktrace:

    error TypeError: Cannot add property AccountUrl, object is not extensible
    at eval (retrieveRecord.js:4)
    at Array.forEach ()
    at eval (retrieveRecord.js:4)

    Please advise how to correct.

    Thanks.
    HS

  3. Its worked but if we want to display only 5 records at a time and wants to have a view all button to display all records in a window then how to implement this?

    • In that case, you need to implement the pagination to display the 5 records. And to display view all you have to develop your own piece of logic as displaying all 5 records in one window is not great as per me but your requirement can be different.

  4. Hi, if I am calling this component from another component and passing the recordid then no data is coming in UI. could you pls tell me how to solve this?

      • Yes I have added one variable @api caseId in this and calling this component from another component with the caseid. In apex filtering cases based upon id.

        data table JS:

        @api caseId
        connectedcallback(){this.getAllCaseDetails();}

        getAllCaseDetails(){
        console.log(‘case id >>’+this.caseId); ///is coming as undefined
        fetchCases({Cased:this.caseId})
        .then(data =>{
        console.log(‘data >>’+data);

        Other component from where i am calling data table:

  5. Hi, This is not working for me, do we need to create caseurl and AccountUrl etc., fields in respective objects? In my case I have a dropped down which have all the sobjects and on change of combobox I am forming the columns as below:

    [{“label”:”Id”,”fieldName”:”Id”,”type”:”text”},{“label”:”Name”,”fieldName”:”recordurl”,”type”:”url”,”typeAttributes”:{“label”:{“fieldName”:”Name”},”target”:”_self”},”sortable”:true}]

    and used the same code as you using the foreach loop assigned the url to recordurl

    • You do not need to create any field on Account or case Object. You need to prepare those fields inside your JavaScript Method. If you are following the way I did and doing it correctly you will be able to get it correct.

  6. Hi Amit, I have a scenario where I want to show Row Action button under lightning data table based on some condition.
    means like if case. Priority==”High” then only Row Action button(View Details) under table should be visible else it will be false in LWC.

  7. Thanks for sharing .. I have faced issues with url opens new tab whatever used either _blank/_self/_top/_parent .. have you experienced same and any solution? I use case is to open in same tab.

  8. How to make the url field land on a specific url ? by placing the url into target ? like target: “www.google.com” ?
    I tried this but its not going to the google.com.
    My field value is “member xyz”. after clicking on it its redirecting to
    https://member%20xyz%20template

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Hi Team, I have two types of record type(Business Account, Vendor Account) in account object. i need to display list of account records(All Records) with Pagination.(Need to display the fields are name, phone, email, record type name ) and each records have individual checkbox, if i am selecting checkbox is equal true, based on record type name need to show some fields in my popup window. Please help me this scenario Thanks, Suhirdass SHow to Add Hyperlink and icons in Lightning:datatable
5/5

Stuck in coding limbo?

Our courses unlock your tech potential