0

I have formula fields that show HTML values and I need to show them in a custom related record data table

enter image description here

What I have tried so far.

And to be honest, I'm frustrated right now because it's not working for me, maybe I'm tired and I don't see the issue or something, but I feel like I have tried everything.

Parent Component -

HTML

<template>
    <lightning-card icon-name={iconName} title={objectLabel}>
        <c-rich-datatable key-field="Id" data={tableData} columns={tableColumns} hide-checkbox-column
                      wrap-text-max-lines="3"></c-rich-datatable>
    </lightning-card>
</template>

JS

import { LightningElement, api, wire, track} from 'lwc';
import getIconName from '@salesforce/apex/ICRM_DynamicRelatedRecordsList_Ctrlr.getIconName';
import getObjectLabel from '@salesforce/apex/ICRM_DynamicRelatedRecordsList_Ctrlr.getObjectLabel';
import getFieldSet from '@salesforce/apex/ICRM_DynamicRelatedRecordsList_Ctrlr.getFieldSet';

export default class IcrmDrrl extends LightningElement {
    @api recordId;
    @api objectName = '';
    @api relatedField = '';
    @api fieldList = '';
    @api recordsToDisplay = 0;
    @track iconName = '';
    @track objectLabel = '';
    @track tableData = [];
    @track tableColumns = [];
    @track result = [];

    @wire(getIconName, { objectName: '$objectName' })
     wiredIcon({ error, data}) {
         if(data) {
            this.iconName = data;
         } else if (error) {
            this.error = error;
            this.iconName = undefined;
         }
     }

    @wire(getObjectLabel, { sobjectApiName: '$objectName' })
    wiredLabel({ error, data}) {
        if(data) {
            this.objectLabel = data;
        } else if (error) {
            this.error = error;
            this.objectLabel = undefined;
        }
    }

    @wire(getFieldSet, {
        sObjectName: '$objectName',
        listOfFields: '$fieldList',
        recordId: '$recordId',
        relationshipField: '$relatedField',
        recordsToDisplay: '$recordsToDisplay'
    }) wiredResults({error, data}) {
        if (data) {
            this.tableData = data.listData;
            this.result = data.columns;
        } else if (error) {
            this.error = error;
            this.tableData = undefined;
            this.result = undefined;
        }
    }

    connectedCallback() {
        this.result.map((col) => {
            return (col.type = "richText");
        });
        console.log(JSON.stringify(this.result));
        this.tableColumns = this.result;
        console.log(JSON.stringify(this.tableColumns));
    }

}

CustomDatatable component

HTML

<template>
</template>

JS

import LightningDatatable from "lightning/datatable";
import richTextColumnType from "./richTextColumnType.html";

/**
 * Custom component that extends LightningDatatable
 * and adds a new column type
 */
export default class richDatatable extends LightningDatatable {
    static customTypes = {
        // custom type definition
        richtext: {
            template: richTextColumnType,
            standardCellLayout: true
        }
    }
}

HTML template for customDatatable

<template>
    <!-- a template for cell. File in the myCustomDatatable directory -->
    <template if:true={wrapText}>
        <lightning-formatted-rich-text value={value} class="slds-truncate">
        </lightning-formatted-rich-text>
    </template>
    <template if:false={wrapText}>
        <lightning-formatted-rich-text value={value}>
        </lightning-formatted-rich-text>
    </template>
</template>

And still can't make it work.

Thanks in advance to sfdcfox for helping me with the last issue.

Thanks.

1
  • You're probably missing out the need to change type attribute for the rich fieldName in the Columns. – Sachin Hooda Oct 27 '20 at 4:45
3

You're probably missing out type attribute in the columns for the formula field. Since it's a formula-text field. The default text column is applied.

You need to add a type attribute to the columns for that field that should be like,

  columns = [
    // standard text column
    { label: "Text Column", fieldName: "textCol", wrapText: true },
    {
      label: "Text Column",
      fieldName: "richField",
      type: "richText",
      wrapText: true,
    },
    {
      label: "Rich Text",
      fieldName: "richTextCol__c",
      type: "richText", //specify a type attribute here 
      wrapText: true,
    },
  ];

You can see a live demo here.

enter image description here

Once you get columns from apex. You need to change the type attribute before assigning it to the columns attribute.

  connectedCallback() {
    result.map((col) => {
      if (col.fieldName === YOUR_RICH_TEXT_FIELD) {
        return (col.type = "richText");
      }
    });
   this.columns = result;
  }

Apex Class

public with sharing class ICRM_DynamicRelatedRecordsList_Ctrlr {

    @AuraEnabled (Cacheable= true)
    public static String getIconName(String objectName) {
        String u;
        List<Schema.DescribeTabSetResult> tabSetDesc = Schema.describeTabs();
        List<Schema.DescribeTabResult> tabDesc = new List<Schema.DescribeTabResult>();
        List<Schema.DescribeIconResult> iconDesc = new List<Schema.DescribeIconResult>();

        for (Schema.DescribeTabSetResult tsr : tabSetDesc) {
            tabDesc.addAll(tsr.getTabs());
        }

        for (Schema.DescribeTabResult tr : tabDesc) {
            if (objectName == tr.getSobjectName()) {
                if (tr.isCustom() == true) {
                    iconDesc.addAll(tr.getIcons());
                } else {
                    u = 'standard:' + objectName.toLowerCase();
                }
            }
        }
        for (Schema.DescribeIconResult ir : iconDesc) {
            if (ir.getContentType() == 'image/svg+xml') {
                u = 'custom:' + ir.getUrl().substringBetween('custom/', '.svg').substringBefore('_');
                break;
            }
        }
        return u;
    }

    @AuraEnabled (Cacheable= true)
    public static String getObjectLabel(String sobjectApiName) {
        Schema.SObjectType sobjectType = Schema.getGlobalDescribe().get(sobjectApiName);
        Schema.DescribeSObjectResult sobjectDescribe = sobjectType.getDescribe();
        return sobjectDescribe.getLabelPlural();
    }

    @AuraEnabled (Cacheable= true)
    public static ColumnAndDataWrapper getFieldSet(String sObjectName, String listOfFields, Id recordId, String relationshipField, Integer recordsToDisplay) {
        ColumnAndDataWrapper cdw = new ColumnAndDataWrapper();
        List<Columns> columns = new List<Columns>();
        String fieldsToFetch = '';

        Map<String, Schema.SObjectType> gd = Schema.getGlobalDescribe();
        Schema.SObjectType ctype = gd.get(sObjectName);
        Map<String, Schema.SObjectField> fmap = ctype.getDescribe().fields.getMap();

        List<String> fieldList = listOfFields.replaceAll(' ','').split(',');

        // Generating a list of columns
        for (String f : fieldList) {
            if (f == 'Name') {
                // Uncomment and replace to allow go to record by clicking name
                // columns.add(new Columns(fmap.get(f).getDescribe().getLabel(), 'linkName', 'url'));
                columns.add(new Columns(fmap.get(f).getDescribe().getLabel(), 'Name', 'text'));
            } else {
                columns.add(new Columns(fmap.get(f).getDescribe().getLabel(), f, String.valueOf(fmap.get(f).getDescribe().getType()).toLowerCase()));
            }
            if (fieldsToFetch != '') {
                fieldsToFetch += ',';
            }
            fieldsToFetch += f;
        }

        // Get the records of requested object
        List<SObject> listData;
        if (recordsToDisplay == null) {
            listData = Database.query('SELECT Id, ' + fieldsToFetch + ' FROM ' + sObjectName + ' WHERE ' + relationshipField + ' = :recordId ');
        } else if (recordsToDisplay != null && recordsToDisplay > 0) {
            listData = Database.query('SELECT Id, ' + fieldsToFetch + ' FROM ' + sObjectName + ' WHERE ' + relationshipField + ' = :recordId LIMIT ' + recordsToDisplay);
        }
        cdw.columns = columns;
        cdw.listData = listData;
        return cdw;
    }

    public class Columns {
        @AuraEnabled public String label;
        @AuraEnabled public String fieldName;
        @AuraEnabled public String type;
        public Columns(String label, String fieldName, String type) {
            this.label = label;
            this.fieldName = fieldName;
            this.type = type;
        }
    }

    public class ColumnAndDataWrapper {
        @AuraEnabled public List<Columns> columns;
        @AuraEnabled public List<SObject> listData;
    }

}
7
  • the issue is that I'm not manually building up the Columns anywhere in the solution, I'm retrieving the columns dynamically from the Apex controller (in herethis.columns = data.columns;), is there a way to assign attributes to all columns? – AjFmO Oct 27 '20 at 14:28
  • You need to change it before you put it into the columns. Edited! – Sachin Hooda Oct 27 '20 at 14:42
  • I will update the code. Still is not working, IDK what's wrong. – AjFmO Oct 27 '20 at 15:35
  • Can you try hard coding type attribute for that particular fieldName and see if it works? Simply data.columns[fieldIndex].type = 'richText';. this.tableColumns= data.columns; in your getFieldSet. – Sachin Hooda Oct 27 '20 at 16:04
  • I did this if (data) { this.tableData = data.listData; data.columns[1].type = 'richText'; this.tableColumns = data.columns; } Table did not render and in console got an error Cannot assign to read only property 'type' of object '#<Object>' – AjFmO Oct 27 '20 at 16:14
0

I found the problem, a big part of the issue was a typo in the CustomDatatable component.

export default class richDatatable extends LightningDatatable {
    static customTypes = {
        // custom type definition
     --->   richText: {
            template: richTextColumnType,
            standardCellLayout: true
        }
    }

I also refactored the main LWC JS code, by implementing this (as seen in Mr. Eric Smith DatatableV2)

    @wire(getFieldSet, {
        sObjectName: '$objectName',
        listOfFields: '$fieldList',
        recordId: '$recordId',
        relationshipField: '$relatedField',
        recordsToDisplay: '$recordsToDisplay'
    }) wiredResults({error, data}) {
        if (data) {
            this.tableData = data.listData;
    --->    data.columns.forEach(column => {
                this.result.push({
                    label: column.label,
                    fieldName: column.fieldName,
                    type: 'richText'
                });
            })
    --->    this.tableColumns = this.result;
        } else if (error) {
            this.error = error;
            this.tableData = undefined;
            this.tableColumns = undefined;
            this.result = undefined;
        }
    }

This way I was able to see the values properly formated.

Many thanks to Sachin, who took the time to help me. And Mr. Eric Smith for sharing his knowledge and keeping it open to the world.

1
  • freaking typo... sigh... smh – AjFmO Oct 27 '20 at 22:30

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.