[SalesForce] Hyperlink record name LWC datatable

I am trying to fetch List of sobjects and show them in data table. I want to add a hyperlink to record name. I am using @wired property to dynamically get records depending on the search term.

my test.js

@track data = [];
@track error;
@track columns = [{
        label: 'Some name', fieldName: 'linkName', type: 'url', sortable: true, 
        typeAttributes: {label: { fieldName: 'Name' },value:{fieldName: 'linkName'}, target: '_blank'}}];


@wire(apexSearch,{searchTerm: "$searchTerm1"})

wiredTenders({error, data}) {
   if (data) {
       this.data = Object.assign({}, data);
       var a  = JSON.parse(JSON.stringify(this.data));

       for (var i = 0; i < data.length; i++) {
           console.log('1.5)'+(a[i]));
            if(a[i].linkName) a[i].linkName = '/'+a[i].Id;
        }
        console.log('2)'+data);
    } else if (error) {
        this.error = error;
    }
 }

The linkName never gets filled i.e I cannot see a hyperlink and also no data shows up in data table. I checked that the var a contains the list of objects. enter image description here
I used this.data = Object.assign({}, data); due to the explanation in this post: Uncaught TypeError: 'set' on proxy: trap returned falsish for property Name

Any suggestions would be helpful. Thanks!

Best Answer

here is a solution that works perfectly. I display a list of opportunity and add a hyperlink on the column name of the data table. To do that, you have to create a wrapper class in you apex controller like this:

public with sharing class GetAllOpportunities {
   @AuraEnabled(cacheable=true)
    public static List<DataTableWrapper> getAllOpps() {
        List<Opportunity> listOpp = [SELECT Id, Name ,StageName, CloseDate 
                                     FROM Opportunity Order By Name asc];

        List<DataTableWrapper> response = new List<DataTableWrapper>();
        for(Opportunity opp : listOpp){
            DataTableWrapper obj = new DataTableWrapper();
            obj.oppId = opp.Id;
            obj.name = opp.Name;
            obj.nameUrl = '/'+opp.Id;
            obj.stageName = opp.StageName;
            obj.closeDate = opp.CloseDate;
            response.add(obj);
        }

        return response;
    }

    private class DataTableWrapper {
        @AuraEnabled
        public Id oppId {get;set;}
        @AuraEnabled
        public String name {get;set;}
        @AuraEnabled
        public String nameUrl {get;set;}
        @AuraEnabled
        public String stageName {get;set;}
        @AuraEnabled
        public Date closeDate {get;set;}
    }


}

note the nameUrl attribute, I'll use it in the js file.

here is the html file:

<template>
    <lightning-card  title="Opportinity List">
        <lightning-datatable data={opportunities} columns={columns} key-field="Id"></lightning-datatable>        
    </lightning-card> 
</template>

And Finally, the js file:

import { LightningElement ,wire,track} from 'lwc';
import getAllOpps from '@salesforce/apex/GetAllOpportunities.getAllOpps';

export default class OpportunityList extends LightningElement {
    @track columns = [
        {
            label: 'Opportunity name',
            fieldName: 'nameUrl',
            type: 'url',
            typeAttributes: {label: { fieldName: 'name' }, 
            target: '_blank'},
            sortable: true
        },
        {
            label: 'Stage Name',
            fieldName: 'stageName',
            type: 'text',
            sortable: true
        },
        {
            label: 'Close date',
            fieldName: 'closeDate',
            type: 'date',
            sortable: true
        }

    ];

    @track error;
    @track opportunities = [];


    @wire(getAllOpps)
    wiredOpps({error,data}) {
        if (data) {
            this.opportunities = data;
            this.error = undefined;
        } else if (error) {
            this.error = error;
            this.opportunities = undefined;
        }
    }
}

==========================================================================

Update

=========================================================================

This code below does the same thing without creating any wrapper class. We can only use JS.

import { LightningElement ,wire,track} from 'lwc';
import getAllOpps from '@salesforce/apex/GetAllOpportunities.getAllOpps';

export default class OpportunityList extends LightningElement {
    @track columns = [
        {
            label: 'Opportunity name',
            fieldName: 'nameUrl',
            type: 'url',
            typeAttributes: {label: { fieldName: 'Name' }, 
            target: '_blank'},
            sortable: true
        },
        {
            label: 'Stage Name',
            fieldName: 'StageName',
            type: 'text',
            sortable: true
        },
        {
            label: 'Close date',
            fieldName: 'CloseDate',
            type: 'date',
            sortable: true
        }

    ];

    @track error;
    @track opportunities = [];


    @wire(getAllOpps)
    wiredOpps(result) {
        const { data, error } = result;
        if(data) {
            let nameUrl;
            this.opportunities = data.map(row => { 
                nameUrl = `/${row.Id}`;
                return {...row , nameUrl} 
            })
            this.error = null;
        }
        if(error) {
            this.error = error;
            this.opportunities = [];
        }
    }
}

Apex class

public with sharing class GetAllOpportunities {
   @AuraEnabled(cacheable=true)
    public static List<Opportunity> getAllOpps() {
        return [SELECT Id, Name ,StageName, CloseDate FROM Opportunity Order By Name asc];
    }

}
Related Topic