• Salesforce Development 45
  • NEWBIE
  • 0 Points
  • Member since 2020

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 2
    Questions
  • 1
    Replies
Here is the code I'm using to get account information via a lookup, I can see the values selected in the first row but when I add a new row i can't see the value selected in the search box. However, when I save the component the values I selected in the rows are being saved. The only problem is the values selected are not visible in the search box from 2nd row.

1) LightningLookupEvent.evt
 
<aura:event type="COMPONENT" description="by this event we are pass the selected record id in the parent component">
    <aura:attribute name="recordIdByAccEvent" type="String"/>
   <!-- <aura:attribute name="ObjectAPIName" type="String"/> -->
</aura:event>

2) LightningLoookup.cmp
 
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,force:lightningQuickAction" access="global"
  controller="LightningLookupController">

	  <!--<ltng:require styles="{!$Resource.SLDS213 +'/assets/styles/salesforce-lightning-design-system.css'}"/>-->
		<!-- For External Use -->
    <aura:attribute name="objectAPIName" type="String" />
    <aura:attribute name="serialno" type="Integer" />
	<aura:attribute name="listSize" type="Integer" default="5"/>
    <aura:attribute name="readOnly" type="boolean"/>
    <!-- <aura:attribute name="IconName" type="string" default=""/> -->
    <aura:attribute name="nameIcon" type="String" required="true" default="custom:custom57"/>
    <!-- <aura:attribute name="selectedRecord" type="sObject" default="{}" description="Use,for store SELECTED sObject Record"/> -->
    <!-- For External Use -->

    <!-- For Internal Use -->
	<aura:attribute name="queryString" type="String"/>
	<aura:attribute name="templateSearchList" type="Object"/>
    <aura:attribute name="NoResultBooleanValue" type="boolean"/>
    <aura:attribute name="spinnerLoad" type="Boolean" default="" />
    <aura:attribute name="valueSelectedId" type="String" />
    <aura:attribute name="valueSelectedName" type="String" />
    <!-- For Internal Use -->

    <!-- aura handler for spinner -->
  <!--  <aura:handler event="aura:waiting" action="{!c.showSpinner}"/> -->
   <!-- <aura:handler event="aura:doneWaiting" action="{!c.hideSpinner}"/> -->

    <!-- Event for passing the selected record to parent component -->
    <aura:registerEvent name="selectRecordIdEvent" type="c:LightningLookUpEvent"/>

		<form aura:id="lookupForm" >
            <div>
                
                      <!-- this is lookup pill, it will display when user select any value from the list -->
                      <div id="{!'lookuppill'+v.objectAPIName}" class="slds-pill-container slds-hide" onmouseover="{!c.onCrossChange}" onmouseout="{!c.onCrossChangeOut}">
                          
                      <span class="slds-pill" style="width:100%">
                      <span class="slds-icon_container slds-combobox__input-entity-icon" title="record">
                      <lightning:icon iconName="{!v.nameIcon}" size="x-small"/>
                      <span class="slds-assistive-text"></span> 
                      </span>
                      <span aura:id="recordList" class="slds-pill__label slds-p-left_x-large" onmouseover="{!c.onCrossChange}" onmouseout="{!c.onCrossChangeOut}">

                         {!v.valueSelectedName}

                     </span>
                            <img class="slds-icon slds-input__icon slds-input__icon_right slds-icon-text-default" src="{!$Resource.LookUpPNGImage+ '/IP_Lightning/Close.PNG'}" style="width:24px; cursor: pointer; height:25px;margin-top: -0.115remrem;margin-right: -0.0rem;" id="{!'closeButton1'+v.objectAPIName}" onclick="{!c.removePill}" title="Close" draggable="false" />

                            <img class="slds-hide slds-icon slds-input__icon slds-input__icon_right slds-icon-text-default" src="{!$Resource.LookUpPNGImage+ '/IP_Lightning/CloseForLookUp.PNG'}" style="width:24px; cursor: pointer; height:25px;margin-top: -0.115remrem;margin-right: -0.0rem;" id="{!'closeButton2'+v.objectAPIName}" onclick="{!c.removePill}" title="Close" draggable="false" />

                   </span>
                   </div>

                      <!--This section is to show the input text box for Searching template-->
                       <div id="{!'smallDiv'+v.objectAPIName}" class="slds-show slds-input-has-icon slds-input-has-icon--right">
                            <aura:if isTrue="{!v.spinnerLoad}">
                              <div class="slds-float_right" aura:id="spinner">
                                 <lightning:spinner class="slds-spinner_brand slds-float_right" size="small" />
                              </div>
                            </aura:if>

                            <img class="slds-show slds-icon slds-input__icon slds-input__icon_right slds-icon-text-default" src="{!$Resource.LookUpPNGImage+ '/IP_Lightning/Search.PNG'}" style="width:24px; cursor: pointer; height:25px;margin-top: -0.66rem;margin-right: -0.4rem;" id="{!'searchbutton'+v.objectAPIName}"  title="Search" draggable="false"/>

                            <input type="text" id="{!'inputMain'+v.objectAPIName}" class="slds-input slds-has-input-focus" value="{!v.queryString}" onkeyup="{!c.onValueChange}" placeholder="Search.." autocomplete="off"  />

                      </div>

                       <!--This section is to show the list of records names as a drop down list after the user types a string and the search result is retrieved-->
                       <div class="slds-show" id="{!'listShow'+v.objectAPIName}">
                           <ul class="customdropdown" role="presentation" style="display: block; min-width: auto; max-width: 100% ; width: 100%;">
                          <!--    <ul style="min-height:40px;margin-top:0px !important" class="slds-listbox slds-listbox_vertical slds-dropdown slds-dropdown_fluid slds-lookup__menu slds" role="listbox">  -->
                            <aura:iteration items="{!v.templateSearchList}" var="list" >
                                <div class="slds-box slds-box_xx-small slds-show slds-input-has-icon" >
                                     <li class="slds-dropdown__item  " data-id="{!list.Id}" data-name="{!list.Name}" onclick="{!c.selectedTemplate}" role="presentation">
                                         <a href="javascript:void(0);" data-id="{!list.Id}" data-name="{!list.Name}" data-value="{!list}" role="menuitem" tabindex="0" >
                                             <span class="slds-icon_container  slds-combobox__input-entity-icon" title="record">
                                                <lightning:icon iconName="{!v.nameIcon}" size="x-small"/>
                                                <span class="slds-assistive-text"></span>
                                             </span>
                                             <span  data-name="{!list.Name}" data-id="{!list.Id}" data-value="{!list}" class="FontNotification slds-text-align_left slds-truncate slds-p-left_large">{!list.Name}</span>
                                         </a>
                                    </li>
                                </div>
                            </aura:iteration>
                           </ul>
                      </div>
                      <!-- this section will display if there are no matching values with the searched string -->
                      <ul class="{!v.NoResultBooleanValue == true ? 'slds-dropdown__list' : 'slds-hide'}" role="menu">
                        <div class="slds-box slds-box_xx-small">
                           <li class="slds-dropdown__item" role="presentation">
                              <span  class="slds-truncate slds-p-left_medium"><b>No Match Found</b></span>

                           </li>
                        </div>
                      </ul>
              </div>
    </form>
</aura:component>

3) LightningLookUpController.js
 
({
    
    onValueChange : function(component, event, helper) {
        var target = event.target;           
        console.log('target.value :: '+target.value);
        var objectName = component.get("v.objectAPIName");
        var inputBox=document.getElementById("inputMain"+objectName);
        
        
        //Clear the timer
        clearTimeout(window.timer);
        //Setting the timer to 0.5 second / 500 ms. After the user stops typing, 0.5 seconds later the below server call will be made
        window.timer = setTimeout($A.getCallback(function(){
            // if the input text box is blank, template search list is given null value
            if(target.value==''){
                console.log('inside query empty string');
                component.set('v.templateSearchList', null);
                component.set('v.queryString',null);
            }else{
                var action = component.get('c.getObjectNameList');
                action.setParams({
                    "typedString" : target.value,
                    "objectApi" : component.get("v.objectAPIName"),
                    "num" : component.get("v.listSize")
                });
                action.setCallback(this,function(response){
                    var state = response.getState();
                    if(state =='SUCCESS'){
                        
                        // Result contains the list of template names along with its IDs
                        var result = response.getReturnValue();
                        console.log('Success and the template list are-->'+JSON.stringify(result, null, 4));
                        if(result != null){
                            // set the list of templates retrieved from server as a drop down list below the inputText box in the component
                            if(result.length>0){
                                component.set("v.NoResultBooleanValue",false);
                            }else{
                                console.log('Inside another lse of null ');
                                component.set("v.NoResultBooleanValue",true);
                            }
                            var tempList = document.getElementById("listShow"+objectName);
                            $A.util.removeClass(tempList, 'slds-hide');
                            
                            component.set('v.templateSearchList', result);
                        }else{
                            // If there is no result, show a message saying no result found
                        }
                    }
                });
                $A.enqueueAction(action);
            }
            
        }),500);
    },
    
    //show spinner
    showSpinner : function (component) {
        component.set("v.spinnerLoad","true");
    },
    
    //Hide spinner
    hideSpinner : function (component) {
        component.set("v.spinnerLoad","false");
    },
    
    //when user will click on the value in a the record list
    selectedTemplate : function(component, event, helper){
        var target =event.target || event.srcElement;
        console.log('clicked on select template -->');
        var recordsId = target.dataset.id;
        var objectName = component.get("v.objectAPIName");
        
        var recordsName = target.dataset.name;
        console.log('recordsName-->'+recordsName);
        console.log('recordsId-->'+recordsId);
        
        
        //Populate the textinput field with the complete name of the Objects Record template since it is selected by the user.
        component.set("v.valueSelectedId",recordsId);
        component.set("v.valueSelectedName",recordsName);
        
        var recordIdForEvent = component.get("v.valueSelectedId");
        
        // call the event
        var compEvent = component.getEvent("selectRecordIdEvent");
        console.log('compEvent value :: '+compEvent);
        // set the Selected sObject Record to the event attribute.
        compEvent.setParams({"recordIdByAccEvent" : recordsId, "objectAPINameEvent" : objectName});
        // fire the event
        compEvent.fire();
        
        
        //hide input textbox after clicking on the record from the list
        //var tempBoxx = document.getElementById("smallDiv"+objectName);
      var tempBoxx = document.querySelectorAll("smallDiv"+objectName);;
        for(var i=0; i<tempBoxx.length; i++) {
  		console.log('dom tempBoxx :: '+tempBoxx[i]);
        $A.util.removeClass(tempBoxx[i], 'slds-show');
        $A.util.addClass(tempBoxx[i], 'slds-hide');
        }
        
        
        //show lookup pill with selected value after clicking on the record from the list
      //  var pill = document.getElementById("lookuppill"+objectName);
        var pill = document.querySelectorAll("lookuppill"+objectName);
        for(var i=0; i<pill.length; i++) {
        console.log('pill :: '+pill);
        $A.util.removeClass(pill[i], 'slds-hide');
        $A.util.addClass(pill[i], 'slds-show');
        }
        
        //Hide the iterating list of template names
        var tempList = document.getElementById("listShow"+objectName);
        console.log('Checking tempList :: '+tempList);
        $A.util.removeClass(tempList, 'slds-show');
        $A.util.addClass(tempList, 'slds-hide');
        component.set('v.templateSearchList', null);
        component.set("v.valueSelectedId",null);
        
    },
    
    //when user will click on the cross button in the looup pill
    removePill : function(component, event, helper){
        
        var objectName = component.get("v.objectAPIName");
        
        //hide lookup pill with selected value after clicking on the cross button in the looup pill
        var pill = document.getElementById("lookuppill"+objectName);
        console.log('dom pill :: '+pill);
        $A.util.removeClass(pill, 'slds-show');
        $A.util.addClass(pill, 'slds-hide');
        
        //show input textbox after clicking on the cross button in the looup pill
        var tempBoxx = document.getElementById("smallDiv"+objectName);
        console.log('dom tempBoxx :: '+tempBoxx);
        $A.util.removeClass(tempBoxx, 'slds-hide');
        $A.util.addClass(tempBoxx, 'slds-show');
        
        component.set("v.queryString",null);
        component.set("v.templateSearchList",null);
        component.set("v.valueSelectedId",null);
        component.set("v.valueSelectedName",null);
    },
    
    //when user will hover  on the cross button cross button will be live
    onCrossChange : function(component, event, helper){
        console.log('onCrossChange onCrossChange onCrossChange :: ');
        
        var objectName = component.get("v.objectAPIName");
        
        var close1 = document.getElementById("closeButton1"+objectName);
        console.log('dom close1 :: '+close1);
        $A.util.removeClass(close1, 'slds-show');
        $A.util.addClass(close1, 'slds-hide');
        
        var close2 = document.getElementById("closeButton2"+objectName);
        console.log('dom closeButton2 :: '+close2);
        $A.util.removeClass(close2, 'slds-hide');
        $A.util.addClass(close2, 'slds-show');
        
    },
    
    //when user will hover  on the cross button cross button will be live
    onCrossChangeOut  : function(component, event, helper){
        console.log('onCrossChangeOut onCrossChangeOut onCrossChangeOut :: ');
        
        var objectName = component.get("v.objectAPIName");
        
        var close2 = document.getElementById("closeButton2"+objectName);
        console.log('dom closeButton2 :: '+close2);
        $A.util.removeClass(close2, 'slds-show');
        $A.util.addClass(close2, 'slds-hide');
        
        var close1 = document.getElementById("closeButton1"+objectName);
        console.log('dom close1 :: '+close1);
        $A.util.removeClass(close1, 'slds-hide');
        $A.util.addClass(close1, 'slds-show');
        
        
    },
    
})

4) LightningLookUp.css
.THIS .customdropdown{
   left: 0%;
    position: absolute;
    background-color: white;
    
}

5)LightningLookupController.apxc
 
public class LightningLookupController {

   @AuraEnabled
    public static List < sObject > getObjectNameList(String typedString, String objectApi, Integer num) {
        system.debug('ObjectName-->' + objectApi);
        String searchKey = '%'+ typedString + '%';

        List < sObject > returnList = new List < sObject > ();

        // Create a Dynamic SOQL Query For Fetch Record List with LIMIT 5
        String sQuery =  'select id, Name from ' +objectApi + ' where Name LIKE: searchKey order by createdDate DESC limit '+num;
        List < sObject > lstOfRecords = Database.query(sQuery);

        for (sObject obj: lstOfRecords) {
            returnList.add(obj);
        }
        return returnList;
    }

}

 
Hello Salesforce Gurus, I am pretty new to Salesforce development and I am trying to create a custom lightning component with add/delete rows functionality with lookup fields in the grid. I can successfully select the values for lookup fields. However, when I try to save the values of lookup fields the values don't get passed over to the Intended object and it shows blank values. Any help would be really appreciated, I've been working on this lookup field for like last three days without much success.

Thank you all for the help!
This is the lightning component where I am selecting the lookup field 'User', added a custom field User in accounts and this component has been named as Sample.cmp

<aura:component controller="AuraSampleController" implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction,lightning:isUrlAddressable,lightning:actionOverride" access="global">
     
    <aura:attribute name="accountList" type="Account[]"/>
    <aura:attribute name="selectedLookUpRecord" type="sObject" default="{}"/>
     
   

    <div class="slds-m-around--xx-large">
        <div class="slds-float_right slds-p-bottom_small">
            <h1 class="slds-page-header__title">Add Row 
                <lightning:buttonIcon iconName="utility:add"  size="large" variant="bare" alternativeText="Add" onclick="{!c.addRow}"/>
            </h1>
        </div>
        <div class="container-fluid">        
            <table class="slds-table slds-table_bordered slds-table_cell-buffer"> 
                <thead>
                    <tr class="slds-text-title_caps">
                        <th scope="col">
                            <div class="slds-truncate">#</div>
                        </th>
                        <th scope="col">
                            <div class="slds-truncate" title="Account Name">Account Name</div>
                        </th>
                        <th scope="col">
                            <div class="slds-truncate" title="Account Number">Account Number</div>
                        </th>
                        <th scope="col">
                            <div class="slds-truncate" title="Phone">Phone</div>
                        </th>
                        <th scope="col">
                            <div class="slds-truncate" title="Action">User</div>
                        </th>
                        <th scope="col">
                            <div class="slds-truncate" title="Action">Action</div>
                        </th>
                        
                        
                    </tr>
                </thead>   
                <tbody>      
                    <aura:iteration items="{!v.accountList}" var="acc" indexVar="index">
                        <tr>
                            <td> 
                                {!index + 1}
                            </td>
                            <td>
                                <lightning:input name="accName" type="text" required="true" maxlength="50" label="Account Name" value="{!acc.Name}" />
                            </td>
                            <td>
                                <lightning:input name="accNumber" type="text"  maxlength="10" label="Account Number" value="{!acc.AccountNumber}" />
                            </td>
                            <td>
                                <lightning:input name="accPhone" type="phone" maxlength="10" label="Phone" value="{!acc.Phone}" />
                            </td> 
                            <td>
            			 <c:customLookup objectAPIName="User" IconName="standard:Contact" selectedRecord="{!v.selectedLookUpRecord}"/>   
                    <!-- <c:LightningLookUp objectAPIName="account" NameIcon="standard:account" /> -->   
			</td> 
                            <td>
                                <a onclick="{!c.removeRow}" data-record="{!index}">
                                    <lightning:icon iconName="utility:delete" size="small" alternativeText="Delete"/>
                                    <span class="slds-assistive-text">Delete</span>
                                </a>
                            </td> 
                        </tr>
                    </aura:iteration>
                </tbody>
            </table>
            <div class="slds-align_absolute-center slds-p-top_small">
                <lightning:button variant="brand" label="Submit" title="Brand action" onclick="{!c.save}" />
            </div>
        </div>
    </div>
</aura:component>
 
SampleController.js

({
    addRow: function(component, event, helper) {
        helper.addAccountRecord(component, event);
    },
     
    removeRow: function(component, event, helper) {
        //Get the account list
        var accountList = component.get("v.accountList");
        //Get the target object
        var selectedItem = event.currentTarget;
        //Get the selected item index
        var index = selectedItem.dataset.record;
        accountList.splice(index, 1);
        component.set("v.accountList", accountList);
    },
     
    save: function(component, event, helper) {
        if (helper.validateAccountList(component, event)) {
            helper.saveAccountList(component, event);
            
        }
    },
})
 
SampleHelper.js

({
    addAccountRecord: function(component, event) {
        //get the account List from component  
        var accountList = component.get("v.accountList");
        //Add New Account Record
        accountList.push({
            'sobjectType': 'Account',
            'Name': '',
            'AccountNumber': '',
            'Phone': '',
            'User__c':''
        });
        component.set("v.accountList", accountList);
    },
     
    validateAccountList: function(component, event) {
        //Validate all account records
        var isValid = true;
        var accountList = component.get("v.accountList");
        for (var i = 0; i < accountList.length; i++) {
            if (accountList[i].Name == '') {
                isValid = false;
                alert('Account Name cannot be blank on row number ' + (i + 1));
            }
        }
        return isValid;
    },
     
    saveAccountList: function(component, event, helper) {
        //Call Apex class and pass account list parameters
        var action = component.get("c.saveAccounts");
        action.setParams({
       "accList": component.get("v.accountList")
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                component.set("v.accountList", []);
                alert('Account records saved successfully');
            }
        }); 
        $A.enqueueAction(action);
    },
  
})
 
AuraSampleController.apxc

public with sharing class AuraSampleController{
     
    @AuraEnabled
    public static void saveAccounts(List<Account> accList){
        Insert accList;
    }
}
 
customLookup.cmp


<aura:component controller="customLookUpController" implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global">
    <!--declare attributes--> 
    <aura:attribute name="selectedRecord" type="sObject" default="{}" description="Use,for store SELECTED sObject Record"/>
    <aura:attribute name="listOfSearchRecords" type="List" description="Use,for store the list of search records which returns from apex class"/>
    <aura:attribute name="SearchKeyWord" type="string"/>
    <aura:attribute name="objectAPIName" type="string" default=""/>
    <aura:attribute name="IconName" type="string" default=""/>
    <aura:attribute name="label" type="string" default=""/>
    <aura:attribute name="Message" type="String" default=""/>
    <!--declare events hendlers-->  
   
    <aura:handler name="oSelectedRecordEvent" event="c:selectedsObjectRecordEvent" action="{!c.handleComponentEvent}"/>
    <aura:registerevent name ="selectRecordIdEvent"  type="c:LightningLookUpEvent"/>
    
    <!-- https://www.lightningdesignsystem.com/components/lookups/ --> 
    
    <div onmouseleave="{!c.onblur}" aura:id="searchRes" class="slds-form-element slds-lookup slds-is-close" data-select="single">
        <label class="slds-form-element__label" for="lookup-348">{!v.label}</label>
        <!--This part is for display search bar for lookup-->  
        <div class="slds-form-element__control">
            
            <div class="slds-input-has-icon slds-input-has-icon--right">
                <!-- This markup is for when an record is selected -->
                <div aura:id="lookup-pill" class="slds-pill-container slds-hide">
                     <lightning:pill class="pillSize" label="{!v.selectedRecord.Name}" name="{!v.selectedRecord.Name}" onremove="{! c.clear }">
                          <aura:set attribute="media">
                             <lightning:icon iconName="{!v.IconName}" size="x-small" alternativeText="{!v.IconName}"/>
                          </aura:set>
                      </lightning:pill>
                </div>
                <div aura:id="lookupField" class="slds-show">
                    <lightning:icon class="slds-input__icon slds-show" iconName="utility:search" size="x-small" alternativeText="search"/>
                    <span class="slds-icon_container  slds-combobox__input-entity-icon" title="record">
                        <lightning:icon class="slds-icon slds-icon slds-icon_small slds-icon-text-default" iconName="{!v.IconName}" size="x-small" alternativeText="icon"/>
                        <span class="slds-assistive-text"></span>
                    </span>
                    <ui:inputText click="{!c.onfocus}" updateOn="keyup" keyup="{!c.keyPressController}" class="slds-lookup__search-input slds-input leftPaddingClass" value="{!v.SearchKeyWord}" placeholder="search.."/>
                </div>   
            </div>
        </div>
        <!--This part is for Display typehead lookup result List-->  
        <ul style="min-height:40px;margin-top:0px !important" class="slds-listbox slds-listbox_vertical slds-dropdown slds-dropdown_fluid slds-lookup__menu slds" role="listbox">
            <lightning:spinner class="slds-hide" variant="brand" size="small" aura:id="mySpinner"/>
            <center> {!v.Message}</center>
            <aura:iteration items="{!v.listOfSearchRecords}" var="singleRec">
                <c:customLookupResults oRecord="{!singleRec}" IconName="{!v.IconName}"/>
              </aura:iteration>  
               
            
        </ul>
    </div>
</aura:component>
 
customLookupController.js

({
   onfocus : function(component,event,helper){
       $A.util.addClass(component.find("mySpinner"), "slds-show");
        var forOpen = component.find("searchRes");
            $A.util.addClass(forOpen, 'slds-is-open');
            $A.util.removeClass(forOpen, 'slds-is-close');
        // Get Default 5 Records order by createdDate DESC  
         var getInputkeyWord = '';
         helper.searchHelper(component,event,getInputkeyWord);
    },
    onblur : function(component,event,helper){       
        component.set("v.listOfSearchRecords", null );
        var forclose = component.find("searchRes");
        $A.util.addClass(forclose, 'slds-is-close');
        $A.util.removeClass(forclose, 'slds-is-open');
    },
    keyPressController : function(component, event, helper) {
       // get the search Input keyword   
         var getInputkeyWord = component.get("v.SearchKeyWord");
       // check if getInputKeyWord size id more then 0 then open the lookup result List and 
       // call the helper 
       // else close the lookup result List part.   
        if( getInputkeyWord.length > 0 ){
             var forOpen = component.find("searchRes");
               $A.util.addClass(forOpen, 'slds-is-open');
               $A.util.removeClass(forOpen, 'slds-is-close');
            helper.searchHelper(component,event,getInputkeyWord);
        }
        else{  
             component.set("v.listOfSearchRecords", null ); 
             var forclose = component.find("searchRes");
               $A.util.addClass(forclose, 'slds-is-close');
               $A.util.removeClass(forclose, 'slds-is-open');
          }
	},
    
  // function for clear the Record Selaction 
    clear :function(component,event,heplper){
         var pillTarget = component.find("lookup-pill");
         var lookUpTarget = component.find("lookupField"); 
        
         $A.util.addClass(pillTarget, 'slds-hide');
         $A.util.removeClass(pillTarget, 'slds-show');
        
         $A.util.addClass(lookUpTarget, 'slds-show');
         $A.util.removeClass(lookUpTarget, 'slds-hide');
      
         component.set("v.SearchKeyWord",null);
         component.set("v.listOfSearchRecords", null );
         component.set("v.selectedRecord", {} );   
    },
    
    
  // This function call when the end User Select any record from the result list.   
    handleComponentEvent : function(component, event, helper) {
    // get the selected Account record from the COMPONETN event 	 
       var selectedAccountGetFromEvent = event.getParam("recordByEvent");
	   component.set("v.selectedRecord" , selectedAccountGetFromEvent); 
       
        var forclose = component.find("lookup-pill");
           $A.util.addClass(forclose, 'slds-show');
           $A.util.removeClass(forclose, 'slds-hide');
  
        var forclose = component.find("searchRes");
           $A.util.addClass(forclose, 'slds-is-close');
           $A.util.removeClass(forclose, 'slds-is-open');
        
        var lookUpTarget = component.find("lookupField");
            $A.util.addClass(lookUpTarget, 'slds-hide');
            $A.util.removeClass(lookUpTarget, 'slds-show');  
      
	},
})
 
customLookupHelper.js

({
	searchHelper : function(component,event,getInputkeyWord) {
	  // call the apex class method 
     var action = component.get("c.fetchLookUpValues");
      // set param to method  
        action.setParams({
            'searchKeyWord': getInputkeyWord,
            'ObjectName' : component.get("v.objectAPIName")
          });
      // set a callBack    
        action.setCallback(this, function(response) {
          $A.util.removeClass(component.find("mySpinner"), "slds-show");
            var state = response.getState();
            if (state === "SUCCESS") {
                var storeResponse = response.getReturnValue();
              // if storeResponse size is equal 0 ,display No Result Found... message on screen.                }
                if (storeResponse.length == 0) {
                    component.set("v.Message", 'No Result Found...');
                } else {
                    component.set("v.Message", '');
                }
                // set searchResult list with return value from server.
                component.set("v.listOfSearchRecords", storeResponse);
            }
 
        });
      // enqueue the Action  
        $A.enqueueAction(action);
    
	},
})
 
customLookup.css

.THIS .leftPaddingClass {
    padding-left: 2rem;
}
 
.THIS .pillSize{
 width:100%;
}
 
customLookUpController.apxc

public class customLookUpController {
@AuraEnabled
    public static List < sObject > fetchLookUpValues(String searchKeyWord, String ObjectName) {
        system.debug('ObjectName-->' + ObjectName);
        String searchKey = searchKeyWord + '%';
        
        List < sObject > returnList = new List < sObject > ();
      
        // Create a Dynamic SOQL Query For Fetch Record List with LIMIT 5   
        String sQuery =  'select id, Name from ' +ObjectName + ' where Name LIKE: searchKey order by createdDate DESC limit 5';
        List < sObject > lstOfRecords = Database.query(sQuery);
        
        for (sObject obj: lstOfRecords) {
            returnList.add(obj);
        }
        return returnList;
    }
}
 
customLookupResults.cmp

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global">
	<aura:attribute name="oRecord" type="sObject" />
        <aura:attribute name="IconName" type="string"/> 
 
  <!--Register the component level event-->
    <aura:registerEvent name="oSelectedRecordEvent" type="c:selectedsObjectRecordEvent"/>
 
    
    <li role="presentation" class="slds-listbox__item" onclick="{!c.selectRecord}">
        <span 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" title="Description of icon when needed">
                    <lightning:icon iconName="{!v.IconName}" class="slds-icon slds-icon_small" size="small" alternativeText="icon"/>
                    <span class="slds-assistive-text">Description of icon</span>
                  </span>
              </span>    
              <span class="slds-media__body">  
                  <span class="slds-listbox__option-text slds-listbox__option-text_entity">{!v.oRecord.Name}</span>
              </span>
        </span>
    </li>
</aura:component>
 
customLookupResultsController.js

({
   selectRecord : function(component, event, helper){      
    // get the selected record from list  
      var getSelectRecord = component.get("v.oRecord");
    // call the event   
      var compEvent = component.getEvent("oSelectedRecordEvent");
    // set the Selected sObject Record to the event attribute.  
         compEvent.setParams({"recordByEvent" : getSelectRecord });  
    // fire the event  
         compEvent.fire();
    },
})
 
selectedsObjectRecordEvent.evt

<aura:event type="COMPONENT" description="by this event we are pass the selected sObject(lookup list record) in the parent component">
    <aura:attribute name="recordByEvent" type="sObject"/>
</aura:event>
Hello Salesforce Gurus, I am pretty new to Salesforce development and I am trying to create a custom lightning component with add/delete rows functionality with lookup fields in the grid. I can successfully select the values for lookup fields. However, when I try to save the values of lookup fields the values don't get passed over to the Intended object and it shows blank values. Any help would be really appreciated, I've been working on this lookup field for like last three days without much success.

Thank you all for the help!
This is the lightning component where I am selecting the lookup field 'User', added a custom field User in accounts and this component has been named as Sample.cmp

<aura:component controller="AuraSampleController" implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction,lightning:isUrlAddressable,lightning:actionOverride" access="global">
     
    <aura:attribute name="accountList" type="Account[]"/>
    <aura:attribute name="selectedLookUpRecord" type="sObject" default="{}"/>
     
   

    <div class="slds-m-around--xx-large">
        <div class="slds-float_right slds-p-bottom_small">
            <h1 class="slds-page-header__title">Add Row 
                <lightning:buttonIcon iconName="utility:add"  size="large" variant="bare" alternativeText="Add" onclick="{!c.addRow}"/>
            </h1>
        </div>
        <div class="container-fluid">        
            <table class="slds-table slds-table_bordered slds-table_cell-buffer"> 
                <thead>
                    <tr class="slds-text-title_caps">
                        <th scope="col">
                            <div class="slds-truncate">#</div>
                        </th>
                        <th scope="col">
                            <div class="slds-truncate" title="Account Name">Account Name</div>
                        </th>
                        <th scope="col">
                            <div class="slds-truncate" title="Account Number">Account Number</div>
                        </th>
                        <th scope="col">
                            <div class="slds-truncate" title="Phone">Phone</div>
                        </th>
                        <th scope="col">
                            <div class="slds-truncate" title="Action">User</div>
                        </th>
                        <th scope="col">
                            <div class="slds-truncate" title="Action">Action</div>
                        </th>
                        
                        
                    </tr>
                </thead>   
                <tbody>      
                    <aura:iteration items="{!v.accountList}" var="acc" indexVar="index">
                        <tr>
                            <td> 
                                {!index + 1}
                            </td>
                            <td>
                                <lightning:input name="accName" type="text" required="true" maxlength="50" label="Account Name" value="{!acc.Name}" />
                            </td>
                            <td>
                                <lightning:input name="accNumber" type="text"  maxlength="10" label="Account Number" value="{!acc.AccountNumber}" />
                            </td>
                            <td>
                                <lightning:input name="accPhone" type="phone" maxlength="10" label="Phone" value="{!acc.Phone}" />
                            </td> 
                            <td>
            			 <c:customLookup objectAPIName="User" IconName="standard:Contact" selectedRecord="{!v.selectedLookUpRecord}"/>   
                    <!-- <c:LightningLookUp objectAPIName="account" NameIcon="standard:account" /> -->   
			</td> 
                            <td>
                                <a onclick="{!c.removeRow}" data-record="{!index}">
                                    <lightning:icon iconName="utility:delete" size="small" alternativeText="Delete"/>
                                    <span class="slds-assistive-text">Delete</span>
                                </a>
                            </td> 
                        </tr>
                    </aura:iteration>
                </tbody>
            </table>
            <div class="slds-align_absolute-center slds-p-top_small">
                <lightning:button variant="brand" label="Submit" title="Brand action" onclick="{!c.save}" />
            </div>
        </div>
    </div>
</aura:component>
 
SampleController.js

({
    addRow: function(component, event, helper) {
        helper.addAccountRecord(component, event);
    },
     
    removeRow: function(component, event, helper) {
        //Get the account list
        var accountList = component.get("v.accountList");
        //Get the target object
        var selectedItem = event.currentTarget;
        //Get the selected item index
        var index = selectedItem.dataset.record;
        accountList.splice(index, 1);
        component.set("v.accountList", accountList);
    },
     
    save: function(component, event, helper) {
        if (helper.validateAccountList(component, event)) {
            helper.saveAccountList(component, event);
            
        }
    },
})
 
SampleHelper.js

({
    addAccountRecord: function(component, event) {
        //get the account List from component  
        var accountList = component.get("v.accountList");
        //Add New Account Record
        accountList.push({
            'sobjectType': 'Account',
            'Name': '',
            'AccountNumber': '',
            'Phone': '',
            'User__c':''
        });
        component.set("v.accountList", accountList);
    },
     
    validateAccountList: function(component, event) {
        //Validate all account records
        var isValid = true;
        var accountList = component.get("v.accountList");
        for (var i = 0; i < accountList.length; i++) {
            if (accountList[i].Name == '') {
                isValid = false;
                alert('Account Name cannot be blank on row number ' + (i + 1));
            }
        }
        return isValid;
    },
     
    saveAccountList: function(component, event, helper) {
        //Call Apex class and pass account list parameters
        var action = component.get("c.saveAccounts");
        action.setParams({
       "accList": component.get("v.accountList")
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                component.set("v.accountList", []);
                alert('Account records saved successfully');
            }
        }); 
        $A.enqueueAction(action);
    },
  
})
 
AuraSampleController.apxc

public with sharing class AuraSampleController{
     
    @AuraEnabled
    public static void saveAccounts(List<Account> accList){
        Insert accList;
    }
}
 
customLookup.cmp


<aura:component controller="customLookUpController" implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global">
    <!--declare attributes--> 
    <aura:attribute name="selectedRecord" type="sObject" default="{}" description="Use,for store SELECTED sObject Record"/>
    <aura:attribute name="listOfSearchRecords" type="List" description="Use,for store the list of search records which returns from apex class"/>
    <aura:attribute name="SearchKeyWord" type="string"/>
    <aura:attribute name="objectAPIName" type="string" default=""/>
    <aura:attribute name="IconName" type="string" default=""/>
    <aura:attribute name="label" type="string" default=""/>
    <aura:attribute name="Message" type="String" default=""/>
    <!--declare events hendlers-->  
   
    <aura:handler name="oSelectedRecordEvent" event="c:selectedsObjectRecordEvent" action="{!c.handleComponentEvent}"/>
    <aura:registerevent name ="selectRecordIdEvent"  type="c:LightningLookUpEvent"/>
    
    <!-- https://www.lightningdesignsystem.com/components/lookups/ --> 
    
    <div onmouseleave="{!c.onblur}" aura:id="searchRes" class="slds-form-element slds-lookup slds-is-close" data-select="single">
        <label class="slds-form-element__label" for="lookup-348">{!v.label}</label>
        <!--This part is for display search bar for lookup-->  
        <div class="slds-form-element__control">
            
            <div class="slds-input-has-icon slds-input-has-icon--right">
                <!-- This markup is for when an record is selected -->
                <div aura:id="lookup-pill" class="slds-pill-container slds-hide">
                     <lightning:pill class="pillSize" label="{!v.selectedRecord.Name}" name="{!v.selectedRecord.Name}" onremove="{! c.clear }">
                          <aura:set attribute="media">
                             <lightning:icon iconName="{!v.IconName}" size="x-small" alternativeText="{!v.IconName}"/>
                          </aura:set>
                      </lightning:pill>
                </div>
                <div aura:id="lookupField" class="slds-show">
                    <lightning:icon class="slds-input__icon slds-show" iconName="utility:search" size="x-small" alternativeText="search"/>
                    <span class="slds-icon_container  slds-combobox__input-entity-icon" title="record">
                        <lightning:icon class="slds-icon slds-icon slds-icon_small slds-icon-text-default" iconName="{!v.IconName}" size="x-small" alternativeText="icon"/>
                        <span class="slds-assistive-text"></span>
                    </span>
                    <ui:inputText click="{!c.onfocus}" updateOn="keyup" keyup="{!c.keyPressController}" class="slds-lookup__search-input slds-input leftPaddingClass" value="{!v.SearchKeyWord}" placeholder="search.."/>
                </div>   
            </div>
        </div>
        <!--This part is for Display typehead lookup result List-->  
        <ul style="min-height:40px;margin-top:0px !important" class="slds-listbox slds-listbox_vertical slds-dropdown slds-dropdown_fluid slds-lookup__menu slds" role="listbox">
            <lightning:spinner class="slds-hide" variant="brand" size="small" aura:id="mySpinner"/>
            <center> {!v.Message}</center>
            <aura:iteration items="{!v.listOfSearchRecords}" var="singleRec">
                <c:customLookupResults oRecord="{!singleRec}" IconName="{!v.IconName}"/>
              </aura:iteration>  
               
            
        </ul>
    </div>
</aura:component>
 
customLookupController.js

({
   onfocus : function(component,event,helper){
       $A.util.addClass(component.find("mySpinner"), "slds-show");
        var forOpen = component.find("searchRes");
            $A.util.addClass(forOpen, 'slds-is-open');
            $A.util.removeClass(forOpen, 'slds-is-close');
        // Get Default 5 Records order by createdDate DESC  
         var getInputkeyWord = '';
         helper.searchHelper(component,event,getInputkeyWord);
    },
    onblur : function(component,event,helper){       
        component.set("v.listOfSearchRecords", null );
        var forclose = component.find("searchRes");
        $A.util.addClass(forclose, 'slds-is-close');
        $A.util.removeClass(forclose, 'slds-is-open');
    },
    keyPressController : function(component, event, helper) {
       // get the search Input keyword   
         var getInputkeyWord = component.get("v.SearchKeyWord");
       // check if getInputKeyWord size id more then 0 then open the lookup result List and 
       // call the helper 
       // else close the lookup result List part.   
        if( getInputkeyWord.length > 0 ){
             var forOpen = component.find("searchRes");
               $A.util.addClass(forOpen, 'slds-is-open');
               $A.util.removeClass(forOpen, 'slds-is-close');
            helper.searchHelper(component,event,getInputkeyWord);
        }
        else{  
             component.set("v.listOfSearchRecords", null ); 
             var forclose = component.find("searchRes");
               $A.util.addClass(forclose, 'slds-is-close');
               $A.util.removeClass(forclose, 'slds-is-open');
          }
	},
    
  // function for clear the Record Selaction 
    clear :function(component,event,heplper){
         var pillTarget = component.find("lookup-pill");
         var lookUpTarget = component.find("lookupField"); 
        
         $A.util.addClass(pillTarget, 'slds-hide');
         $A.util.removeClass(pillTarget, 'slds-show');
        
         $A.util.addClass(lookUpTarget, 'slds-show');
         $A.util.removeClass(lookUpTarget, 'slds-hide');
      
         component.set("v.SearchKeyWord",null);
         component.set("v.listOfSearchRecords", null );
         component.set("v.selectedRecord", {} );   
    },
    
    
  // This function call when the end User Select any record from the result list.   
    handleComponentEvent : function(component, event, helper) {
    // get the selected Account record from the COMPONETN event 	 
       var selectedAccountGetFromEvent = event.getParam("recordByEvent");
	   component.set("v.selectedRecord" , selectedAccountGetFromEvent); 
       
        var forclose = component.find("lookup-pill");
           $A.util.addClass(forclose, 'slds-show');
           $A.util.removeClass(forclose, 'slds-hide');
  
        var forclose = component.find("searchRes");
           $A.util.addClass(forclose, 'slds-is-close');
           $A.util.removeClass(forclose, 'slds-is-open');
        
        var lookUpTarget = component.find("lookupField");
            $A.util.addClass(lookUpTarget, 'slds-hide');
            $A.util.removeClass(lookUpTarget, 'slds-show');  
      
	},
})
 
customLookupHelper.js

({
	searchHelper : function(component,event,getInputkeyWord) {
	  // call the apex class method 
     var action = component.get("c.fetchLookUpValues");
      // set param to method  
        action.setParams({
            'searchKeyWord': getInputkeyWord,
            'ObjectName' : component.get("v.objectAPIName")
          });
      // set a callBack    
        action.setCallback(this, function(response) {
          $A.util.removeClass(component.find("mySpinner"), "slds-show");
            var state = response.getState();
            if (state === "SUCCESS") {
                var storeResponse = response.getReturnValue();
              // if storeResponse size is equal 0 ,display No Result Found... message on screen.                }
                if (storeResponse.length == 0) {
                    component.set("v.Message", 'No Result Found...');
                } else {
                    component.set("v.Message", '');
                }
                // set searchResult list with return value from server.
                component.set("v.listOfSearchRecords", storeResponse);
            }
 
        });
      // enqueue the Action  
        $A.enqueueAction(action);
    
	},
})
 
customLookup.css

.THIS .leftPaddingClass {
    padding-left: 2rem;
}
 
.THIS .pillSize{
 width:100%;
}
 
customLookUpController.apxc

public class customLookUpController {
@AuraEnabled
    public static List < sObject > fetchLookUpValues(String searchKeyWord, String ObjectName) {
        system.debug('ObjectName-->' + ObjectName);
        String searchKey = searchKeyWord + '%';
        
        List < sObject > returnList = new List < sObject > ();
      
        // Create a Dynamic SOQL Query For Fetch Record List with LIMIT 5   
        String sQuery =  'select id, Name from ' +ObjectName + ' where Name LIKE: searchKey order by createdDate DESC limit 5';
        List < sObject > lstOfRecords = Database.query(sQuery);
        
        for (sObject obj: lstOfRecords) {
            returnList.add(obj);
        }
        return returnList;
    }
}
 
customLookupResults.cmp

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global">
	<aura:attribute name="oRecord" type="sObject" />
        <aura:attribute name="IconName" type="string"/> 
 
  <!--Register the component level event-->
    <aura:registerEvent name="oSelectedRecordEvent" type="c:selectedsObjectRecordEvent"/>
 
    
    <li role="presentation" class="slds-listbox__item" onclick="{!c.selectRecord}">
        <span 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" title="Description of icon when needed">
                    <lightning:icon iconName="{!v.IconName}" class="slds-icon slds-icon_small" size="small" alternativeText="icon"/>
                    <span class="slds-assistive-text">Description of icon</span>
                  </span>
              </span>    
              <span class="slds-media__body">  
                  <span class="slds-listbox__option-text slds-listbox__option-text_entity">{!v.oRecord.Name}</span>
              </span>
        </span>
    </li>
</aura:component>
 
customLookupResultsController.js

({
   selectRecord : function(component, event, helper){      
    // get the selected record from list  
      var getSelectRecord = component.get("v.oRecord");
    // call the event   
      var compEvent = component.getEvent("oSelectedRecordEvent");
    // set the Selected sObject Record to the event attribute.  
         compEvent.setParams({"recordByEvent" : getSelectRecord });  
    // fire the event  
         compEvent.fire();
    },
})
 
selectedsObjectRecordEvent.evt

<aura:event type="COMPONENT" description="by this event we are pass the selected sObject(lookup list record) in the parent component">
    <aura:attribute name="recordByEvent" type="sObject"/>
</aura:event>