2

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. Commented Oct 27, 2020 at 4:45

2 Answers 2

4

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
    Commented Oct 27, 2020 at 14:28
  • You need to change it before you put it into the columns. Edited! Commented Oct 27, 2020 at 14:42
  • I will update the code. Still is not working, IDK what's wrong.
    – AjFmO
    Commented Oct 27, 2020 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. Commented Oct 27, 2020 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
    Commented Oct 27, 2020 at 16:14
1

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
    Commented Oct 27, 2020 at 22:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .