Version 2
This is Version 2 of the Salesforce Lightning Lookup Component. I had one of those, ‘Why didn’t I do it like that instead?‘ moments in the shower this morning. Essentially, it’s less code as I’ve done away with the rendering of the inner list components and plumped straight for throwing the Apex Controller results into an attribute and using an <aura:iteration> to render them. The original version is here for reference.
Note: There appears to be a bug with using <aura:if> in the AccountLookup component. If you experience difficulty with this, a workaround can be found here
On with the show …
I’ve been playing around with Salesforce Lightning components and one of the obvious things that seems to be missing is a UI component to lookup a record in a Salesforce custom object and return its Id.
This was really simple in Visualforce. You could just use an <apex:inputField> tag and bind it to an objects lookup field in your controller. Salesforce would take care of the rest. Lightning, however, is a different beast and centres around building client side apps or components in Javascript and utilising various API’s for dealing with any server side requests.
There’s quite a bit of code here so I’ve added it all to a github repository. (Links at the bottom)
Design
There were a few things to consider:
- It should work both within a desktop app and within the Salesforce Lightning mobile app.
- It should be intuitive and have the look and feel of a lightning app.
- It should be reusable, easily configured and plumbed into another component or app.
Cake
As I said, there’s quite a bit of code so before we begin, like all good cake recipes, let’s look at the finished result (6Mb Animated GIF file, please be patient while it loads):
Look & Feel (using the Salesforce Lightning Design System)
The look and feel comes from the Salesforce Lightning Design System or SLDS for short. This is a prerequisite, so you’ll need to install this before you press ahead and load any of the code into your org. I’m using SLDS092 but you should be able to a later version if you wish. You can install it into your org using the links here. This library provides a whole plethora of CSS, images to make your app and components look like the real deal. It also covers the UI design and how to structure your markup. For the lookup component I’ve used the markup described in the Lookups component of the SLDS. In some cases I’ve replaced the standard HTML tags with lightning framework markup such as <ui:inputText> instead of <input>. I’ve also had to create an <c:svg> component to use instead of the <svg> tag which is not supported in lightning. This is described in the Trailhead module: Build a Lightning App with the Lightning Design System.
Show me the code!
Lightning component bundle: svg
First things first, I need to show you the svg component. You need this so you can render the icons as nice scalable graphics without using the <svg> tag. Now this is pretty much lifted straight from the trailhead module so I’m not going to bore you with how it works. You can check out the trailhead yourself.
Here’s the component markup:
Component
<aura:component > <aura:attribute name="class" type="String" description="CSS classname for the SVG element" /> <aura:attribute name="xlinkHref" type="String" description="SLDS icon path. Ex: /assets/icons/utility-sprite/svg/symbols.svg#download" /> <aura:attribute name="ariaHidden" type="String" default="true" description="aria-hidden true or false. defaults to true" /> </aura:component>
It has a renderer defined which looks like this:
Renderer
({ render: function(component, helper) { //grab attributes from the component markup var classname = component.get("v.class"); var xlinkhref = component.get("v.xlinkHref"); var ariaHidden = component.get("v.ariaHidden"); //return an svg element w/ the attributes var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svg.setAttribute('class', classname); svg.setAttribute('aria-hidden', ariaHidden); svg.innerHTML = '<use xlink:href="'+xlinkhref+'"></use>'; return svg; } })
Apex Controller: LookupSObjectController
We’re going to need an apex controller on the server side to query the database and return the matching records. To do this create the following aura enabled Apex class:
Apex class
/** * Apex Controller for looking up an SObject via SOSL */ public with sharing class LookupSObjectController { /** * Aura enabled method to search a specified SObject for a specific string */ @AuraEnabled public static Result[] lookup(String searchString, String sObjectAPIName) { // Sanitze the input String sanitizedSearchString = String.escapeSingleQuotes(searchString); String sanitizedSObjectAPIName = String.escapeSingleQuotes(sObjectAPIName); List<Result> results = new List<Result>(); // Build our SOSL query String searchQuery = 'FIND \'' + sanitizedSearchString + '*\' IN ALL FIELDS RETURNING ' + sanitizedSObjectAPIName + '(id,name) Limit 50'; // Execute the Query List<List<SObject>> searchList = search.query(searchQuery); // Create a list of matches to return for (SObject so : searchList[0]) { results.add(new Result((String)so.get('Name'), so.Id)); } return results; } /** * Inner class to wrap up an SObject Label and its Id */ public class Result { @AuraEnabled public String SObjectLabel {get; set;} @AuraEnabled public Id SObjectId {get; set;} public Result(String sObjectLabel, Id sObjectId) { this.SObjectLabel = sObjectLabel; this.SObjectId = sObjectId; } } }
Notice the @AuraEnabled keyword. This allows the method to be called from the lightning framework. The lookup method constructs a SOSL query using the passed in search string and the objects API name. It returns a list of Results that contain a label and the Id of the matching SObjects.
Lightning component bundle: LookupSObject
On the client side we have a reusable Lightning component. The component contains attributes to specify the SObjects API Name, the label and plural label to apply along with an optional SVG image path and class from the SLDS. If the latter aren’t specified it uses a default icon, in this case a star.
There are two events registered: updateLookupIdEvent and clearLookupIdEvent. The former is fired when the user chooses an entry from the list, the latter is fired when the user clears a selection (via the cross icon.)
The component uses a keyup event to pass the user entered search string to a controller method. This in turn calls the server side Aura Enabled method.
The markup generated adheres to the SLDS Lookup component design. We’re going to use an <aura:iteration> to bind to the results of the Apex controller search. The matches attribute is where the results will get stored. You’ll notices inside the iteration is <a> element which uses the SObjects Id within the rendered element id so that we can easily capture it within the controller when the item is selected.
The component markup looks like this:
Component
<aura:component controller="LookupSObjectController" > <!-- Required Scripts/Styles --> <!-- Salesforce Lightning Design System : https://www.lightningdesignsystem.com/ --> <ltng:require styles="/resource/SLDS092/assets/styles/salesforce-lightning-design-system-ltng.css" /> <!-- Attributes --> <aura:attribute name="sObjectAPIName" type="String" required="true" description="The API name of the SObject to search" /> <aura:attribute name="label" type="String" required="true" description="The label to assign to the lookup, eg: Account" /> <aura:attribute name="pluralLabel" type="String" required="true" description="The plural label to assign to the lookup, eg: Accounts" /> <aura:attribute name="listIconSVGPath" type="String" default="/resource/SLDS092/assets/icons/custom-sprite/svg/symbols.svg#custom11" description="The static resource path to the svg icon to use." /> <aura:attribute name="listIconClass" type="String" default="slds-icon-custom-11" description="The SLDS class to use for the icon." /> <aura:attribute name="searchString" type="String" description="The search string to find." /> <aura:attribute name="matches" type="LookupSObjectController.Result[]" description="The resulting matches returned by the Apex controller." /> <!-- Events --> <aura:registerEvent name="updateLookupIdEvent" type="c:UpdateLookupId"/> <aura:registerEvent name="clearLookupIdEvent" type="c:ClearLookupId"/> <!-- Lookup Markup : See https://www.lightningdesignsystem.com/components/lookups --> <div class="slds"> <div aura:id="lookup-div" class="slds-lookup" data-select="single" data-scope="single" data-typeahead="true"> <!-- This is the Input form markup --> <div class="slds-form-element"> <label class="slds-form-element__label" for="lookup">{!v.label}</label> <div class="slds-form-element__control slds-input-has-icon slds-input-has-icon--right"> <c:svg class="slds-input__icon" xlinkHref="/resource/SLDS092/assets/icons/utility-sprite/svg/symbols.svg#search" /> <!-- This markup is for when an item is currently selected --> <div aura:id="lookup-pill" class="slds-pill-container slds-hide"> <span class="slds-pill slds-pill--bare"> <span class="slds-pill__label"> <c:svg class="{!'slds-icon ' + v.listIconClass + ' slds-icon--small'}" xlinkHref="{!v.listIconSVGPath}" />{!v.searchString} </span> <button class="slds-button slds-button--icon-bare" onclick="{!c.clear}"> <c:svg class="slds-button__icon" xlinkHref="/resource/SLDS092/assets/icons/utility-sprite/svg/symbols.svg#close" /> <span class="slds-assistive-text">Remove</span> </button> </span> </div> <!-- This markup is for when searching for a string --> <ui:inputText aura:id="lookup" value="{!v.searchString}" class="slds-input" updateOn="keyup" keyup="{!c.search}" /> </div> </div> <!-- This is the lookup list markup. Initially it's hidden --> <div aura:id="lookuplist" class="slds-lookup__menu slds-hide" role="listbox"> <div class="slds-lookup__item"> <button class="slds-button"> <c:svg class="slds-icon slds-icon-text-default slds-icon--small" xlinkHref="/resource/SLDS092/assets/icons/utility-sprite/svg/symbols.svg#search" /> "{!v.searchString}" in {!v.pluralLabel} </button> </div> <ul aura:id="lookuplist-items" class="slds-lookup__list" role="presentation"> <aura:iteration items="{!v.matches}" var="match"> <li class="slds-lookup__item"> <a id="{!globalId + '_id_' + match.SObjectId}" role="option" onclick="{!c.select}"> <c:svg class="{!'slds-icon ' + v.listIconClass + ' slds-icon--small'}" xlinkHref="{!v.listIconSVGPath}" />{!match.SObjectLabel} </a> </li> </aura:iteration> </ul> </div> </div> </div> </aura:component>
There is an associated controller to handle the events. The search method, as mentioned earlier, is called from the keyup event on the search. The select method is called when the user chooses a result from the rendered list. The clear method is called when the user clears the selected item by clicking the cross icon:
Controller
({ /** * Search an SObject for a match */ search : function(cmp, event, helper) { helper.doSearch(cmp); }, /** * Select an SObject from a list */ select: function(cmp, event, helper) { helper.handleSelection(cmp, event); }, /** * Clear the currently selected SObject */ clear: function(cmp, event, helper) { helper.clearSelection(cmp); } })
You’ll notice that each of the methods delegate to a helper. The helper does all the grunt work and looks like this:
Helper
({ /** * Perform the SObject search via an Apex Controller */ doSearch : function(cmp) { // Get the search string, input element and the selection container var searchString = cmp.get('v.searchString'); var inputElement = cmp.find('lookup'); var lookupList = cmp.find('lookuplist'); // Clear any errors and destroy the old lookup items container inputElement.set('v.errors', null); // We need at least 2 characters for an effective search if (typeof searchString === 'undefined' || searchString.length < 2) { // Hide the lookuplist $A.util.addClass(lookupList, 'slds-hide'); return; } // Show the lookuplist $A.util.removeClass(lookupList, 'slds-hide'); // Get the API Name var sObjectAPIName = cmp.get('v.sObjectAPIName'); // Create an Apex action var action = cmp.get('c.lookup'); // Mark the action as abortable, this is to prevent multiple events from the keyup executing action.setAbortable(); // Set the parameters action.setParams({ "searchString" : searchString, "sObjectAPIName" : sObjectAPIName}); // Define the callback action.setCallback(this, function(response) { var state = response.getState(); // Callback succeeded if (cmp.isValid() && state === "SUCCESS") { // Get the search matches var matches = response.getReturnValue(); // If we have no matches, return nothing if (matches.length == 0) { cmp.set('v.matches', null); return; } // Store the results cmp.set('v.matches', matches); } else if (state === "ERROR") // Handle any error by reporting it { var errors = response.getError(); if (errors) { if (errors[0] && errors[0].message) { this.displayToast('Error', errors[0].message); } } else { this.displayToast('Error', 'Unknown error.'); } } }); // Enqueue the action $A.enqueueAction(action); }, /** * Handle the Selection of an Item */ handleSelection : function(cmp, event) { // Resolve the Object Id from the events Element Id (this will be the <a> tag) var objectId = this.resolveId(event.currentTarget.id); // The Object label is the inner text) var objectLabel = event.currentTarget.innerText; // Log the Object Id and Label to the console console.log('objectId=' + objectId); console.log('objectLabel=' + objectLabel); // Create the UpdateLookupId event var updateEvent = cmp.getEvent("updateLookupIdEvent"); // Populate the event with the selected Object Id updateEvent.setParams({ "sObjectId" : objectId }); // Fire the event updateEvent.fire(); // Update the Searchstring with the Label cmp.set("v.searchString", objectLabel); // Hide the Lookup List var lookupList = cmp.find("lookuplist"); $A.util.addClass(lookupList, 'slds-hide'); // Hide the Input Element var inputElement = cmp.find('lookup'); $A.util.addClass(inputElement, 'slds-hide'); // Show the Lookup pill var lookupPill = cmp.find("lookup-pill"); $A.util.removeClass(lookupPill, 'slds-hide'); // Lookup Div has selection var inputElement = cmp.find('lookup-div'); $A.util.addClass(inputElement, 'slds-has-selection'); }, /** * Clear the Selection */ clearSelection : function(cmp) { // Create the ClearLookupId event var clearEvent = cmp.getEvent("clearLookupIdEvent"); // Fire the event clearEvent.fire(); // Clear the Searchstring cmp.set("v.searchString", ''); // Hide the Lookup pill var lookupPill = cmp.find("lookup-pill"); $A.util.addClass(lookupPill, 'slds-hide'); // Show the Input Element var inputElement = cmp.find('lookup'); $A.util.removeClass(inputElement, 'slds-hide'); // Lookup Div has no selection var inputElement = cmp.find('lookup-div'); $A.util.removeClass(inputElement, 'slds-has-selection'); }, /** * Resolve the Object Id from the Element Id by splitting the id at the _ */ resolveId : function(elmId) { var i = elmId.lastIndexOf('_'); return elmId.substr(i+1); }, /** * Display a message */ displayToast : function (title, message) { var toast = $A.get("e.force:showToast"); // For lightning1 show the toast if (toast) { //fire the toast event in Salesforce1 toast.setParams({ "title": title, "message": message }); toast.fire(); } else // otherwise throw an alert { alert(title + ': ' + message); } } })
The doSearch method takes care of calling the Apex controller and storing the results in the matches attribute.
The handleSelection method takes the selected entry and fires the updateLookupIdEvent before modifying the CSS classes to show the Lookup in its selected state.
The clearSelection method fires the clearLookupIdEvent before modifying the CSS classes to revert back to the search state.
The resolveId method splits the SObject Id from the end of the element id. This is used by the handleSelection method to obtain the SObjects Id. Remember, we hashed it in to the <a> elements id.
The displayToast is simply an error logging method that renders a toast popup in the Salesforce1 app or an alert in the browser.
Lightning event: UpdateLookupId
This is the event fired when the user selects an item from search results. It has a single attribute that gets set with the Id of the selected record. You’ll notice this is a component event rather than an application event. Be careful here if you are nesting your components you’ll only be able to handle it in the outermost component. Consider changing it to an Application event if this is an issue.
Event
<aura:event type="COMPONENT" description="Update Lookup Id" > <aura:attribute name="sObjectId" type="Id" required="true" description="The Id of the selected SObject." /> </aura:event>
Lightning event: ClearLookupId
This is the event fired when the user clears the selected item. It has no attributes. Again, you’ll notice this is a component event rather than an application event. Once again, be careful here if you are nesting your components you’ll only be able to handle it in the outermost component. Consider changing it to an Application event if this is an issue.
Event
<aura:event type="COMPONENT" description="Clear the Lookup" />
Ok, great. Now can I see how you use it?
We’re going to wrap this up with an example Account Lookup component which you can plug straight into Salesforce1 via a Component Tab. Since the component implements flexipage:availableForAllPageTypes you could plug it straight into Lightning Builder if you wished. If you wanted to embed it in a Visualforce page you could do that as well. I won’t go into how to do that here but you’ll find details in the Lightning developer documentation.
Lightning component: AccountLookup
First lets look at the component markup. There’s an attribute to hold the Record Id. This is hooked up to the force:recordView component which is only rendered if an Id is present. We have two event handlers listening for the UpdateLookupId and ClearLookupId events. Note the names tie up to the registered events in the LookupSObject component. These event handlers hook up to the components controller via the handleAccountIdUpdate and handleAccountIdClear methods. The LookupSObject component markup takes the labels and icon resources as attributes.
Component
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes"> <!-- Attributes --> <aura:attribute name="recordId" type="Id" description="The current record Id to display" /> <!-- Event handlers --> <aura:handler name="updateLookupIdEvent" event="c:UpdateLookupId" action="{!c.handleAccountIdUpdate}"/> <aura:handler name="clearLookupIdEvent" event="c:ClearLookupId" action="{!c.handleAccountIdClear}"/> <!-- Lookup component --> <c:LookupSObject label="Account" pluralLabel="Accounts" sObjectAPIName="Account" listIconSVGPath="/resource/SLDS092/assets/icons/standard-sprite/svg/symbols.svg#account" listIconClass="slds-icon-standard-account" /> <!-- Record view --> <aura:if isTrue="{!v.recordId!=null}"> <force:recordView recordId="{!v.recordId}" /> </aura:if> </aura:component>
Now lets take a look at the controller. You’ll see the handleAccountIdUpdate method gets the Id from the Event and updates the recordId attribute. The handleAccountIdClear simply nulls the recordId attribute. And that’s it, simples.
Controller
({ /** * Handler for receiving the updateLookupIdEvent event */ handleAccountIdUpdate : function(cmp, event, helper) { // Get the Id from the Event var accountId = event.getParam("sObjectId"); // Set the Id bound to the View cmp.set('v.recordId', accountId); }, /** * Handler for receiving the clearLookupIdEvent event */ handleAccountIdClear : function(cmp, event, helper) { // Clear the Id bound to the View cmp.set('v.recordId', null); } })
If you want to plug the component into Lightning builder, you’ll need to include a design in the component bundle. Since there are no attributes that need passing into our Account Lookup component it just looks like this:
Design
<design:component> </design:component>
Creating the Lightning Component Tab
- Navigate to: Setup->Create->Tabs
- Click on New Lightning Component Tab.
- Select the AccountLookup from the dropdown list.
- Enter a Tab Name.
- Choose a Tab Style.
… and you’re nearly good to go.
All that remains is to add it to the Salesforce1 Navigation.
Navigate to: Setup->Mobile Administration->Salesforce1 Navigation
Add the Component tab to your navigation, fire up the Salesforce1 mobile app and give it a whirl!
Notes:
All the code samples assume the default namespace. If you have your own namespace you’ll need to change the references from c:mything to mynamespace:mything.
If you are using a different version of the SLDS, you’ll need to change the paths in the code from SLDS092 to match your version.
Code and Resources:
The code is based on Version 0.92 of the SLDS: https://www.lightningdesignsystem.com/resources/downloads
Github repository containing all the above code (Note: this includes some updates as per the discussions in the comments thread): https://github.com/tscottdev/Lightning-Lookup
Links and stuff:
Salesforce Lightning Design System
Trailhead: Build a Lightning App with the Lightning Design System
Hello Tony – Gr8 article you have together here, its an awesome control. can you tell me if we can use the component multiple times for different objects on same page? I’m looking to write a component with two Lookup inputs, one for Account and another for Contact. I’m confused if I need multiple Event handlers in this case of just the ones you mentioned in your article?
My intention is to update field like this:
var recId = event.getParam(“sObjectId”);
cmp.set(‘[CustomObj].Account__c’, recId);
and
var recId = event.getParam(“sObjectId”);
cmp.set(‘[CustomObj].Contact__c’, recId);
But this seems like I need two handlerFunctions each for Account and Contact?
As the example stands you’re going to have some confusion if you use multiple instances of the component within another component as you won’t know which one triggered the event.
So a few small code changes are required:
Firstly, add a new attribute to the LookupSObject component, we’ll use this to pass in something to identify the instance of the component:
<aura:attribute name="instanceId" type="String" required="true"
description="An id to identify the instance the component" />
Now add a similar attribute to the UpdateLookupId event:
<aura:attribute name="instanceId" type="String" required="true" description="The id to identify the instance the component" />
In the LookupSObjectHelper method: handleSelction make the changes to where the event is fired to look like:
// Get the Instance Id of the Component
var instanceId = cmp.get('v.instanceId');
// Populate the event with the selected Object Id
updateEvent.setParams({
"sObjectId" : objectId, "instanceId" : instanceId
});
// Fire the event
updateEvent.fire();
Now when we instantiate the component we can add the instance id. We’d modify the AccountLookup component like this:
<c:LookupSObject label="Account" pluralLabel="Accounts" sObjectAPIName="Account" instanceId="MyAccount"
listIconSVGPath="/resource/SLDS092/assets/icons/standard-sprite/svg/symbols.svg#account"
listIconClass="slds-icon-standard-account"
/>
Now we can add some logic in the AccountLookupController handleAccountIdUpdate method to check the externalId and fork the code accordingly:
/**
* Handler for receiving the updateLookupIdEvent event
*/
handleAccountIdUpdate : function(cmp, event, helper) {
// Get the Id from the Event
var accountId = event.getParam("sObjectId");
// Get the Instance Id from the Event
var instanceId = event.getParam("instanceId");
// Determine the instance Id of the component that fired the event
if (instanceId == "MyAccount")
{
// Set the Id bound to the View
cmp.set('v.recordId', accountId);
}
else
{
console.log('Unknown instance id: ' + instanceId);
}
},
Thanks Tony. That is what I was thinking, and with your help I am able to achieve the result. It worked great. Thanks again…
*- Varun*
You’ll need some similar logic in the clear lookup id logic. I’ll update the Git repo with the changes.
I’ve updated the GitHub repo to reflect the changes discussed in this thread. https://github.com/tscottdev/Lightning-Lookup/commits/master
Thanks Tony – I got that to working with your immense help 🙂 … Just one more thing, when I try to load the Component with values preset using button click, it does not show the item preselected?
I’m trying to preload the Lookup field with a value, now I assign the Lookup sobject Field with correct value and when I retrieve the field value I get the value back, but the Lookup component still shows up as Empty input.
Any insights on, where I should look into the code to make it work. I Intend to load the Form with lookup value preselected in the lookup component OR preselect the value on a Button click. Right now I have to search and then select the value manually.
Sorry, I’ve just got back after getting caught in the atrocities in Paris. I’ll post a reply when I’ve got my head in order. Please bear with me.
Hey not to worry. I appreciate all your help anytime. Didn’t knew you were caught up in that, the incident itself is horrifying and is all over the news. My prayers are with the families of the lost souls.
Thanks for you blog post. I’ve made some changes to make it work in a VF page + removed the need to have nested components if you were interested.
Can you share your changes with us? Also, what kind of changes you made regarding need for nested components?
Thanks, please feel free to share or fork the github code.
Here is the code, cleaned up and forked. I have removed some name space stuff, so it’s possible that it may have a couple of errors.
https://github.com/rapsacnz/Lightning-Lookup
Thanks for sharing this Caspar. I’m not in the right headspace to look at it at the moment but look forward to doing so soon.
Yes, I read that you were recently in Paris – that’s rough. Best wishes.
Thanks for the excellent work.
I’m having an error with it :
“Unknown Error : Component class not found: markup://c:XXXXX”. Any idea?
Are you getting this error at runtime or saving a component?
It is working good but I have encountered 1 error where selecting a value from the displayed list and click on cross sign to remove the selected item and again search for a string and select a new value, value is not selected and I got an error at the bottom of page saying: “rerender threw an error in ‘markup://aura:expression’ : Cannot read property ‘childNodes’ of null”
Do you have any idea what is it all about?
I appreciate all the good work
Hi, This looks like a bug in the framework using (Similar to this issue: http://salesforce.stackexchange.com/questions/77730/lightning-component-auraiteration-is-throwing-error-upon-rerendering) Removing the <aura:if> from the AccountLookup.cmp prevents the error. For now suggest wrapping in a DIV and using CSS to hide/show it until Salesforce fix they framework.
Hi Dear,
I am getting this error when searching second time :
“”Something has gone wrong. Cannot read property ‘childNodes’ of null. Please try again.””
Do you have any clue ???
Thanks for helping me out …
Hi Vipul, In case you missed it, please see my previous response to your question in the comment thread. Regards, Tony
Thanks for the reply, Ya I missed it.
What do you mean by “Removing the and from the AccountLookup.cmp “? I did not understand. If possible you can post something here ….
Sorry, WordPress stripped out the html tags. Should read: Removing the <aura:if> from the AccountLookup.cmp prevents the error. For now suggest wrapping in a DIV and using CSS to hide/show it until Salesforce fix they framework.
Thanks for your help , I tried it and at least that error is not coming now…
I was kinda hoping Salesforce might fix it and it would go away on its own as it clearly looks like a platform bug. If I get a chance later I’ll post up the CSS workaround.
yes I am trying something like this :
but I am stuck , record is not visible
opps , It did not came up ..
But it is working now using CSS and Styling
Hi Vipul, I’ve added a new post with the workaround. Cheers, Tony
[…] For those of you having tried to implement the Lightning Lookup from my post: https://meltedwires.com/2015/10/31/salesforce-lightning-lookup-component-v2/ […]