3

Lightning has pre-defined icons for the various standard object types (e.g. Account has the big and small buildings icon) and seems to allow you to associate an icon with a custom object by creating a custom object tab for the given object type.

I am looking for a way to programmatically access the icon detail (in Apex or in some LWC custom component) in a way I can then use that with LWC's lightning-icon component. I first thought about querying with SOQL, but some other means is also fine.

I'm probably looking in completely the wrong place, but here's what I've discovered so far...

I can't find a way to get the icon identities for standard object types. I can live with that since we only use a small number of these in our applications (such as Account, for example) so I can hard-code that "lookup". However, I do want to dynamically use the icons that have been assigned for custom objects.

For custom objects, as I mentioned, I can see that the CustomTab for a custom object (i.e. one named after the object itself and with "customObject" as true) has a Motif field that seems to include the icon name, mixed in with some other text. For example, I can create a custom tab for my custom object that when retrieved through the metadata API looks like:

<CustomTab xmlns="http://soap.sforce.com/2006/04/metadata">
    <customObject>true</customObject>
    <description>Test</description>
    <motif>Custom57: Building Block</motif>
</CustomTab>

I can find "custom57" in the LDS icons library and this is the right icon for what I selected.

Now, what I can't work out is how to query the CustomTab detail since something like:

SELECT Motif FROM CustomTab WHERE customObject = TRUE AND fullName = 'MyCustomObject__c'

simply doesn't work (CustomTab is not a supported SObject type).

I have, in my quest for an answer, come across TabDefinition. This looks promising as an SOQL queryable object. However, it doesn't seem to provide the desired icon identity information.

Anyone know how to get this information programmatically?

4
  • 1
    Not sure about SOQL, but you can access the themeInfo.iconUrl from LWC lightning/uiObjectInfoApi. For learning I had used it for porting my lookup component to lwc component (although never got chance to finish).
    – Raul
    Commented Jul 4, 2019 at 11:19
  • Oooh, thanks for that. As I said, happy to either SOQL it or access somehow from within an LWC component. I'll go have a look and come back to you.
    – Phil W
    Commented Jul 4, 2019 at 11:20
  • 1
    Interestingly this led me to salesforce.stackexchange.com/questions/190454/… (searching for themeInfo iconUrl) which ties in with Mariia's description and example of the icon URL.
    – Phil W
    Commented Jul 4, 2019 at 11:32
  • 1
    @Raul, please could you turn your comment into an answer - it's a good way of handling it in the context of LWC.
    – Phil W
    Commented Jul 4, 2019 at 12:01

4 Answers 4

6

In LWC, its a bit easier to use lightning/uiObjectInfoApi to get the icon information for any custom object, following is pseudo code for Account object:

import { LightningElement, wire } from 'lwc';
import { getObjectInfo } from 'lightning/uiObjectInfoApi';
import ACCOUNT_OBJECT from '@salesforce/schema/Account';

@track themeInfo;

export default class Example extends LightningElement {
    @wire(getObjectInfo, { objectApiName: ACCOUNT_OBJECT })
    handleResult({error, data}) {
        if(data) {


            let objectInformation = data;
            
            // access theme info here
            // icon URL is availe as themeInfo.iconUrl
            this.themeInfo = objectInformation.themeInfo || {};
        }
        if(error) {
            // handle error
        }
    }
}

For learning I thought of porting an old custom lookup aura component to lwc, one feature was to display dynamic icon and my research took me to themeInfo of uiObjectInfoApi which I found to be quite useful. Here is the link to the project.

4

It can be retrieved, but not really clear:

SELECT (SELECT Url FROM Icons) FROM TabDefinition where IsCustom = true AND SobjectName = 'MyCustomObject__c'

You will get as a result something like this as an url:

https://site-momentum-5565-dev-ed.cs90.my.salesforce.com/img/icon/t4v35/custom/custom71_120.png

To retrieve the motif number just get substring after last '/'. And after then substring between 'custom' and '_'.

Hope it helps you solve the problem.

4
  • Thanks for the fast reply! I'm considering whether Raul's approach will work since I want to do this inside an LWC component that then uses the lightning-icon component within it. Will let you know the direction I go.
    – Phil W
    Commented Jul 4, 2019 at 11:24
  • 2
    What's most interesting with this is that multiple icon URLs are returned by this query - different types and sizes (one SVG and several different PNGs that seem to be different sizes). The SVG file naming seems to closely resemble the needed "category:name" format for lightning-icon names, being like ".../custom/custom57.svg" in my case. Restricting to the SVG is easy: "SELECT (SELECT ContentType, Url FROM Icons WHERE ContentType LIKE 'image/svg%') FROM TabDefinition WHERE SobjectName = 'MyCustomObject__c'"
    – Phil W
    Commented Jul 4, 2019 at 11:47
  • I think we are likely to go with Raul's suggestion. The reason I say this is that I'm guessing the LWC infrastructure will automatically select an appropriate format of icon based on device capabilities. However, many many thanks for your very helpful answer.
    – Phil W
    Commented Jul 4, 2019 at 12:03
  • 1
    Not at all, you are welcome! Commented Jul 4, 2019 at 12:04
1

On @raul's solution above, i implemented it, if you are using in LWC, then here's the full code with parsing the objectInformation.themeInfo and retrieving just the icon . It works for both standard and custom objects .

 @wire(getObjectInfo, { objectApiName: "$sobjectName" })
  handleResult({error, data}) { //T01 -> to fetch icon name for object on run time.
      if(data) {
          let objectInformation = data;    
          console.log('--objectInformation-- object--'+JSON.stringify(objectInformation)+ '--'+this.sobjectName) ;     
         let iconUrl  = objectInformation.themeInfo.iconUrl ;
          let objectIcon = '';

if (iconUrl && iconUrl.trim() !== '') {
  const urlList = iconUrl.split('/');
  if (urlList.length > 2) {
    const iconSvg = urlList[urlList.length - 1];
    const iconName = iconSvg.substring(0, iconSvg.lastIndexOf('_'));
    this.iconName = `${urlList[urlList.length - 2]}:${iconName}`;
    console.log('--iconName--'+JSON.stringify(iconName));
  }
}

where sobjectName is the object API name that i was passing fromparent component and had defined it as an api variable. This will vary as per your requirement.

1

I needed to access icon names for Industry Clouds, which have new standard objects, but which may be using custom:icons. I found the getObjectInfos (I tried the bulk version because I have more than one object) to be unsuccessful, so I handled it in Apex. Here's the non-bulkified version of that.

public static String getIconName(String sObjectName){
        String iconName = 'standard:link'; //default icon
        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( sObjectName == tr.getSobjectName() ) {
                iconDesc.addAll(tr.getIcons());
            }
        }
        for (Schema.DescribeIconResult ir : iconDesc) {
            if (ir.getContentType() == 'image/svg+xml'){
                String url = ir.getUrl();
                List<String> urlParts = url.split('/');
                String type = urlParts.get(urlParts.size() - 2);
                String filename = urlParts.get(urlParts.size() - 1);
                filename = filename.replace('.svg', '');
                iconName = type + ':' + filename;
                System.debug('🟢 iconName: ' + iconName);
                break;
            }
        }
        return iconName;
    }

Instead of parsing the URL with substring, as @mariia illarionove does above, I split the url into parts and determined the custom/standard from the url rather than isCustom() method on the DescribeTabResult. The reason is that they're using "custom" icons on new standard objects.

You must log in to answer this question.

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