Custom Lookup Component for Lightning

Poster 2 basic

In this post, I am focusing on the custom lookup component missing as a seeded control in lightning.

Custom Simple Lookup
Custom Simple Lookup

Prerequisites: Basic knowledge of lightning component, Javascript .

Implementation

This implementation requires the following members. The server-side interaction of the component is not included in this implementation, you can develop it yourself, based on the requirement. Comment below if you need any help on that.

  • SimpleLookup.cmp
  • SimpleLookupController.js
  • SimpleLookupHelper.js
  • SimpleLookup.css

SimpleLookup.cmp

<aura:component >
<aura:attribute name="label" type="String" access="global" default="Search"/>
<aura:attribute name="selectedRecord" type="sObject" default="{name:'Account1'}" />
<aura:attribute name="fetchedRecords" type="List" />
<aura:attribute name="searchText" type="String"/>
<div aura:id="lookUpPane" class="slds-form-element slds-lookup slds-is-close" onmouseleave="{!c.onLeaveLookupPane}">
<label class="slds-form-element__label" for="lookup-text">{!v.label}</label>
<div class="slds-form-element__control">
<div aura:id="master-container" class="slds-combobox_container slds-has-object-switcher">
<div class="slds-input-has-icon slds-input-has-icon–right input-container">
<!– This part displays the slds pill –>
<div aura:id="selected-item-pill" class="slds-hide pill-container">
<lightning:pill class="pill-item-size" label="{!v.selectedRecord.name}" name="{!v.selectedRecord.name}" onremove="{! c.remove }">
</lightning:pill>
</div>
<!– This part displays the input control for search–>
<div aura:id="input-area" class="slds-show">
<lightning:icon class="slds-input__icon slds-show" iconName="utility:search " size="x-small" alternativeText="search"/>
<ui:inputText aura:id="searchContent" class="slds-lookup__search-input slds-input input-no-border" value="{!v.searchText}" updateOn="keyup" keyup="{!c.onInputChange}" click="{!c.onSearchInputClick}"/>
</div>
</div>
</div>
</div>
<!–
Lookup container to list down the records matched with the criteria
–>
<div id="listbox-unique-id" class="lookup-container" role="listbox">
<ul class="slds-listbox slds-listbox_vertical slds-dropdown slds-dropdown_fluid slds-lookup__menu" role="presentation">
<aura:iteration var="record" items="{!v.fetchedRecords}" indexVar="index">
<li role="presentation" class="slds-listbox__item" onclick="{!c.selectedRecordRowClick}" data-index="{!index}">
<div id="listbox-option-unique-id-01" class="slds-media slds-listbox__option slds-listbox__option_entity slds-listbox__option_has-meta" role="option">
<!–<span class="slds-media__figure">
<span class="slds-icon_container slds-icon-standard-account" title="Description of icon when needed">
<span class="slds-assistive-text">Description of icon when needed</span>
</span>
</span>–>
<span class="slds-media__body">
<span class="slds-listbox__option-text slds-listbox__option-text_entity">{!record.name}</span>
<span class="slds-listbox__option-meta slds-listbox__option-meta_entity">{!record.description}</span>
</span>
</div>
</li>
</aura:iteration>
</ul>
</div>
</div>
</aura:component>

view raw
SimpleLookup.html
hosted with ❤ by GitHub

In the above component view part, I have declared four aura attributes

  • label – display label of the component
  • fetchedRecords – list of records matched with filter criteria
  • searchText –  content of input textbox, used as filter criteria for record processing
  • selectedRecord – holds the current user selection

The Custom Lookup view splits into three sections

  • Input Container – for inserting search criteria
  • Lookup list with a container – list the matched items based on the input
  • SLDS-pill – to show the selected list item

Please see the code comments for more details.

SimpleLookupController.js

({
onLeaveLookupPane : function(component, event, helper) {
//Search – Input control focus removed on mouse leave
var inputContainerCmp = component.find('master-container');
helper.removeClass(inputContainerCmp,'slds-has-input-focus');
},
remove : function (component, event, helper) {
//Hide the active SLDS – pill
var selectedItemPill = component.find('selected-item-pill');
helper.hideElement(selectedItemPill);
//Show search-input control
var inputElement = component.find('input-area');
helper.showElement(inputElement);
},
onInputChange : function (component, event, helper) {
var searchContent = component.get("v.searchText");
var lookupContainerCmp = component.find("lookUpPane");
if ( searchContent && searchContent.trim().length > 0 ) {
searchContent = searchContent.trim();
helper.addClass(lookupContainerCmp,'slds-is-open');
helper.removeClass(lookupContainerCmp,'slds-is-close');
helper.searchContent(component,searchContent);
} else {
helper.removeClass(lookupContainerCmp,'slds-is-open');
helper.addClass(lookupContainerCmp,'slds-is-close');
}
},
onSearchInputClick : function (component, event, helper) {
//input control foucs enabled by adding focus style class
var inputContainerCmp = component.find('master-container');
helper.addClass(inputContainerCmp,'slds-has-input-focus');
},
selectedRecordRowClick : function (component, event, helper) {
//event triggered on lookup row selection
//fetching the details of selected row and it's index
var targetSource = event.currentTarget;
var selectedIndex = targetSource.dataset.index;
console.log(targetSource,selectedIndex);
var listedRecords = component.get("v.fetchedRecords");
if (listedRecords && listedRecords.length > 0 && +selectedIndex >=0) {
var selectedRecord = listedRecords[selectedIndex];
//Search input control value resets
component.find("searchContent").set("v.value","");
//Hide the lookup
var lookupContainerCmp = component.find("lookUpPane");
helper.removeClass(lookupContainerCmp,'slds-is-open');
helper.addClass(lookupContainerCmp,'slds-is-close');
//Show Selected row content as a SLDS – pill
var selectedItemPill = component.find('selected-item-pill');
helper.showElement(selectedItemPill);
//Hide the search-input control
var inputElement = component.find('input-area');
helper.hideElement(inputElement);
}
}
})

The JS methods mainly focused on the visibility (show or hide) of the view elements rather than doing complex logic.

  • onLeaveLookupPane – to hide the lookup container
  • remove – to hide the slds-pill and show the input text field
  • onInputChange – triggers on the keyup event of the input text field and displays the lookup container with the filtered data as a list by invoking “searchContent helper method.
  • onSearchInputClick – adds the standard SLDS input-focus style
  • selectedRecordRowClick triggers when a list item is selected from the lookup container and displayed the selected list item as an SLDS-pill after hiding the input container.

Please see the code comments for more details.

SimpleLookupHelper.js

({
addClass : function (element, className) {
//Global Aura util method for adding a style class from an aura element
$A.util.addClass(element,className);
},
removeClass : function (element , className) {
//Global Aura util method for removing a style class from an aura element
$A.util.removeClass(element,className);
},
showElement : function (element) {
//To show an aura html element
var self = this;
self.removeClass(element,'slds-hide');
self.addClass(element,'slds-show');
},
hideElement : function (element) {
//To hide an aura html element
var self = this;
self.removeClass(element,'slds-show');
self.addClass(element,'slds-hide');
},
searchContent : function (component,searchContent) {
//The helper method calls sets the matched search content to component view
//Now, it is returing some dummy records
//Note – In your application – you should call the server method here with search query string
//(searchContent)as parameter.
//Matched records should sets to v.fetchedRecords attribute.
var record = [{"name": "Account1","description":"Account . Location1"},
{"name": "Account2","description":"Account . Location2"},
{"name": "Account3","description":"Account . Location3"},
{"name": "Account4","description":"Account . Location4"},
{"name": "Account5","description":"Account . Location5"},
{"name": "Account6","description":"Account . Location6"},
{"name": "Account7","description":"Account . Location7"}
];
component.set("v.fetchedRecords",record);
}
})

The searchContent method is used for assigning sample records to fetchedRecords aura attribute. You can replace the existing sample code with functional one which can fetch the records from the apex controller on the server side.

  • add/removeClass – overridden method for adding or removing style class.
  • Show/HideElement – show or hide the HTML element based on the input

Please see the code comments for more details.

SimpleLookup.css

.THIS .pill-item-size,.THIS .input-container {
width : 100%
}
.THIS .pill-container{
font-size: medium;
margin: .5px;
}
.THIS .input-no-border{
border : transparent;
}
.THIS .input-no-border:focus{
outline: transparent;
border-color: inherit;
-webkit-box-shadow: none;
box-shadow: none;
}

view raw
SimpleLookup.css
hosted with ❤ by GitHub

Custom Simple Lookup
Custom Simple Lookup

Poster 2 basic

Don’t forget to share the post if you like it & bookmark the blog for future references.

If you have any comments or doubts on this post, Please comment on the box below.

2 thoughts on “Custom Lookup Component for Lightning

  1. Nitish Bansal July 19, 2018 / 2:04 am

    This doesn’t seem to work with record edit.

    What are the code changes needed for the same ?

    Moreover, how can I support lookup filter feature in this markup ?

    Like

    • Anil Somasundaran July 19, 2018 / 3:12 am

      I couldn’t understand your point , it will work on the record edit since it is a custom component right?
      To incorporate the filters you need to add view attributes and pass it to the apex controller

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s