Salesforce Lightning – Customizable Polymorphic Lookup Component
If you have been using Salesforce Lightning Experience, you probably are familiar with the Lightning Polymorphic Lookup. For example, you will see it while creating Tasks, in the “Name” and “Related to” fields:
Basically, you get to chose the “type” of SObject; when you type text, a search is performed on the appropriate SObject.
I was tasked with building a Lightning page where I needed similar functionality with some finer tuning:
- the lookup needed to be related to the User object AND a custom picklist field on the User object
- the lookup should only show Users that satisfied certain conditions (example: one standard user)
I wrote a general purpose Polymorphic Lookup that would perform a custom query to choose the records that a user is allowed to select from. The source code can be found here: https://github.com/veenasundara/Lightning-Polymorphic-Lookup
How do you use a Polymorphic Lookup?
I will not describe the details of the component itself, but rather how you would use it. So, here is the how I used it:
<aura:component controller="CmpPolyLookupExampleCtrl"> <aura:attribute name="selectedTeamMemberId" type="String" access="private"/> <aura:attribute name="selectedTeamMemberName" type="String" access="private"/> <aura:attribute name="selectedType" type="String" default="Users" access="private"/> <c:CmpPolymorphLookup lookupLabel="Add Team Members" selectedMenuType="{!v.selectedType}" selectedId="{!v.selectedTeamMemberId}" selectedName="{!v.selectedTeamMemberName}" > <c:CmpPolymorphLookupType type="Users" fetchRecordsMethod="{!c.getUsers}" iconType="standard" iconName="user"> </c:CmpPolymorphLookupType> <c:CmpPolymorphLookupType type="User Groups" fetchRecordsMethod="{!c.getUserGroups}" iconType="standard" iconName="groups"> </c:CmpPolymorphLookupType> </c:CmpPolymorphLookup> </aura:component>
The code above looks like this:
Here’s what selecting “User” does:
And this happens when “User Groups” is selected:
The component CmpPolymorphLookup takes 4 attributes; its “body” contains one CmpPolymorphLookupType component for each “type” that a user can choose from.
CmpPolymorphLookup’s attributes are:
- lookupLabel (optional) – the title that appears above the lookup.
- selectedMenuType – populated by the component when a user selects a “type” from the drop down menu.
- selectedId – populated by the component with the “Id” of the record when a user selects a record from the list.
- selectedName– populated by the component with the “Name” of the record when a user selects a record from the list. You will use this to perform necessary actions when a record has been selected, like so:
aura:handler name="change" value="{!v.selectedTeamMemberName}" action="{!c.TeamMemberSelected}"/>
Since I have 2 “types” (Users and User Groups), you see 2 CmpPolymorphLookupType components in the body of the CmpPolymorphLookup component.
CmpPolymorphLookupType takes 4 attributes:
- type – the text that you would like displayed in the picklist for this type.
- fetchRecordsMethod – the name of the controller method that will be executed when this type is selected, in order to fetch candidate records.
- iconType – used to describe the icon that you would like displayed for this type. This component uses icons from the Lightning design system. This attribute describes which type (action, custom, doctype, standard or utility) of an icon you would like. Please refer to the Lightning Design System documentation. (https://www.lightningdesignsystem.com/icons/) for more information
- iconName – used to further describe the icon that you would like displayed for this type.
What’s so cool about this?
This solution’s flexibility comes from being able to specify fetchRecordsMethod. For each “type”, we will have to create one method in our Apex Controller (CmpPolyLookupExampleCtrl in my case). This method will perform a custom query and return a List<List<String>>.
The inner List will contain 2 members for each record we want to return (key, value). When returning SObject records, this could be the record’s Id and Name. For picklists, it could be the value and label.
In my Apex Controller, CmpPolyLookupExampleCtrl, my getUsers and getUserGroups methods look like this:
// //CmpPolyLookupExampleCtrl.cls // @AuraEnabled public static List<List<String>> getUsers() { User[] users = [Select Id, Name From User Where UserType = 'Standard' and IsActive = true and LastName != 'Site Guest User' order by Name]; List<List<String>> records = new List<List<String>>(); records.add(new List<String>{'All', '--All Users--'}); for(User u : users) { records.add(new List<String>{u.Id, u.Name}); } return records; } @AuraEnabled public static List<List<String>> getUserGroups() { Schema.DescribeFieldResult fieldResult = User.User_Group__c.getDescribe(); List<Schema.PicklistEntry> ple = fieldResult.getPicklistValues(); List<List<String>> records = new List<List<String>>(); Map<String, Schema.PicklistEntry> mapPLEntryByLabel = new Map<String, Schema.PicklistEntry>(); for( Schema.PicklistEntry f : ple) { mapPLEntryByLabel.put(f.getLabel(), f); } List<String> lstLabels = new List<String>(mapPLEntryByLabel.keySet()); lstLabels.sort(); records.add(new List<String>{'All', '--All User Groups--'}); for(String label: lstLabels) { Schema.PicklistEntry pe = mapPLEntryByLabel.get(label); records.add(new List<String>{pe.getValue(), pe.getLabel()}); } return records; }
Note: The component I have written “requires” a custom query. Feel free to modify it to allow for a “default” behavior that will simply select the Id and Name of an SObject with no specific filters. Also, please post below if you find any other ways to customize this component!
See what else you can do with the Customizable Polymorphic Lookup Component. We can help with our custom development services.