[SalesForce] Hyperlink a Record in lightning:datatable

enter image description here

Am trying to accomplish a POC in my project. We have a lightning Datatable using . I could generate a set of records to display on the component. But I need one column to be hyperlinked to navigate to the corresponding record when I click on them. The data table fields and object is passed dynamically at runtime either from Community Page/App Builder page/ Some Lightning container components.

Problem:

I couldn't figure out a way to make the first column as hyperlinked. I tried to work around by creating a formula field with HYPERLINK("/" &Id, "View Record"). But it generates this(Ref My Screenshot) on the data table in UI. If anyone can help with some workaround?

Component:

<aura:component controller="lightningTableController" implements="flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,force:appHostable" access="global" >
<aura:attribute name="title" type="string" default="My Interations" />
<aura:attribute name="recLimit" type="String" default="10" /> 
<aura:attribute name="object" type="string" default="Case" />
<aura:attribute name="fields" type="String" default="RecIdURL__c,FSA_BTO_Date_Of_Service__c,Subject,Type,FSA_BTO_Service_Requested__c" />   
<aura:attribute name="sortedBy" type="string" default="FSA_BTO_Date_Of_Service__c" />
<aura:attribute name="sortedDirection" type="string" default="DESC" />
<aura:attribute name="mydata" type="object" />
<aura:attribute name="mycolumn" type="object" />

<aura:handler name="init" value="{!this}" action="{!c.init}" />

<lightning:card title="{!v.title}" >

    <lightning:datatable data="{!v.mydata}" columns="{!v.mycolumn}" 
                         onsort="{!c.updateColumnSorting}" sortedBy="{!v.sortedBy}" 
                         sortedDirection="{!v.sortedDirection}" 
                         hideCheckboxColumn="true" 
                         onrowselection="{!c.getSelectedName}" keyField="Id" />
</lightning:card>

Controller.JS:

({
init : function(component, event, helper) {
    helper.getLightningTableData(component);
},
updateColumnSorting: function (cmp, event, helper) {
    var fieldName = event.getParam('fieldName');
    var sortDirection = event.getParam('sortDirection');
    cmp.set("v.sortedBy", fieldName);
    cmp.set("v.sortedDirection", sortDirection);
    helper.sortData(cmp, fieldName, sortDirection);
},
getSelectedName: function (component, event) {

    var selectedRows = event.getParam('selectedRows');
    for (var i = 0; i < selectedRows.length; i++){
       console.log('>>>',selectedRows[i].Subject);
    }

  }
})

Helper.JS

({
getLightningTableData : function(component) {
    var recLimit = component.get("v.recLimit");
    var sColumn = component.get("v.fields");
    var sObject = component.get("v.object");
    var action = component.get("c.getsObjectRecords");
    action.setParams({
        ObjectName : sObject,
        fieldstoget : sColumn,
        recLimit : recLimit
    });
    action.setCallback(this,function(response){
    var state = response.getState();
    if(state == 'SUCCESS'){
        var rtnValue = response.getReturnValue();
        component.set("v.mycolumn",rtnValue.tableColumn);
        component.set("v.mydata",rtnValue.tableRecord);
    }
   });
     $A.enqueueAction(action);
},
sortData: function (cmp, fieldName, sortDirection) {
    var data = cmp.get("v.mydata");
    var reverse = sortDirection !== 'asc';
    data.sort(this.sortBy(fieldName, reverse))
    cmp.set("v.mydata", data);
},
sortBy: function (field, reverse, primer) {
    var key = primer ?
        function(x) {return primer(x[field])} :
        function(x) {return x[field]};
    reverse = !reverse ? 1 : -1;
    return function (a, b) {
        return a = key(a), b = key(b), reverse * ((a > b) - (b > a));
    }
  }
})

Design:

<design:component >
<design:attribute name="title" label="Header Title" description="Title for the data table" />
<design:attribute name="object" label="Object API Name" description="API Name of the Object" />
<design:attribute name="fields" label="Fields API Name" />
<design:attribute name="recLimit" label="Number of Records to Display" description="Limit value for SOQL"/>

APEX:

public with sharing class lightningTableController {

@AuraEnabled public static lightningTableWraper getsObjectRecords(String ObjectName,String fieldstoget,Integer recLimit){     

    List<String> lstfieldstoget = fieldstoget.split(',');
    List<lightningTableColumnWrapper> lstTableColumn = new list<lightningTableColumnWrapper> ();

    DescribeSObjectResult objResult = Schema.getGlobalDescribe().get(ObjectName).getDescribe();

    for(String field : lstfieldstoget){
       lightningTableColumnWrapper colWrapper = new lightningTableColumnWrapper();
       DescribeFieldResult fieldResult = objResult.fields.getMap().get(field).getDescribe();
       colWrapper.label = fieldResult.getLabel();
       colWrapper.fieldName = fieldResult.getName();
       colWrapper.type = String.valueof(fieldResult.getType()).toLowerCase();
       colWrapper.sortable = true;
       lstTableColumn.add(colWrapper);
    }
    Id loggedUser = UserInfo.getUserId();
    String queryString = 'Select '+ String.escapeSingleQuotes(String.join(lstfieldstoget,','))+
                         ' from '+ String.escapeSingleQuotes(ObjectName) + ' Limit ' +recLimit;

    LightningTableWraper ltngTableWrapper = new LightningTableWraper();
    ltngTableWrapper.tableRecord = database.query(queryString);
    ltngTableWrapper.tableColumn = lstTableColumn;

    return ltngTableWrapper;

}


 public class lightningTableColumnWrapper {
    @AuraEnabled
    public string label {get;set;}
    @AuraEnabled
    public String fieldName {get;set;}
    @AuraEnabled
    public string type {get;set;}
    @AuraEnabled
    public boolean sortable {get;set;}

}

public class lightningTableWraper{
    @AuraEnabled
    public List<sObject> tableRecord {get;Set;}
    @AuraEnabled
    public List<lightningTableColumnWrapper> tableColumn {get;set;}

  }
}

Best Answer

We can take help of the type: url and typeAttributes: {label: { fieldName: 'linkLabel' }} to show some useful link label of the column;

Working with Column Data

Here we have two options

  1. type possible values are(action, ..., url);
  2. typeAttributes value depends on the type option value like for url we have (label, target);

Here is the example of the same: lightning:datatable

Below is the example of the options:

Type and type attributes usage

And we can also do this type adjustment just before assigning the columns settings to the attribute in the helper(if not want to do in the Apex):

({
  getLightningTableData: function (component) {
    var recLimit = component.get('v.recLimit');
    var sColumn = component.get('v.fields');
    var sObject = component.get('v.object');
    var action = component.get('c.getsObjectRecords');
    action.setParams({
      ObjectName: sObject,
      fieldstoget: sColumn,
      recLimit: recLimit
    });
    action.setCallback(this, function (response) {
      var state = response.getState();
      if (state === 'SUCCESS') {
        var rtnValue = response.getReturnValue();

        rtnValue.tableColumn.forEach(function (column) {
          switch (column.fieldName) {
            case 'Show_Record__c':
              column.type = 'url';
              column['typeAttributes'] = { label: { fieldName: 'Name' } };
              break;

            default:
              break;
          }
        });

        component.set('v.mycolumn', rtnValue.tableColumn);
        component.set('v.mydata', rtnValue.tableRecord);
      }
    });
    $A.enqueueAction(action);
  },
  /* more methods */
})
Related Topic