3

I'm using a custom lightning component in an app and that app is being used in a VF page, I have created a component for look up thing, since we dont have any standard components/tags for that, And this custom component is working fine when used out side page, Cant figure out where i'm wrong, Any help is appreciated.

VF Page

    <apex:page standardController="Traffic__c" sidebar="false" showHeader="false" standardStylesheets="false">

    <apex:includeLightning />

    <div id="lightning"/>
<div id="lightning2"/>
    <script>

        $Lightning.use("c:createNewTraffic", function() {
            $Lightning.createComponent("c:CreateTraffic",
                  {},
                  "lightning2",
                  function(cmp) {
                    // do some stuff
              });
        });   
            $Lightning.use("c:createNewTraffic", function() {
            $Lightning.createComponent("c:AccountLookup",
                  {},
                  "lightning",
                  function(cmp) {
                    // do some stuff
              });
        });
    </script>
</apex:page>

App:

<aura:application access="GLOBAL" extends="ltng:outApp">
     <aura:dependency resource="c:CreateTraffic" /> 
    <aura:dependency resource="c:AccountLookup" />  
</aura:application>

AccountLookup.cmp:

<!-- 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/SLDSv0122/assets/icons/standard-sprite/svg/symbols.svg#account"
    listIconClass="slds-icon-standard-account"
/>

AccountLookupController.js :

({
    /**
     * 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);
    }
})

LookUpSobject.cmp :

<aura:component controller="LookupSObjectController" implements="force:appHostable,flexipage:availableForAllPageTypes,force:hasRecordId" access="global">
    <!-- Required Scripts/Styles -->
    <!-- Salesforce Lightning Design System : https://www.lightningdesignsystem.com/ -->
    <ltng:require styles="/resource/SLDSv0122/assets/styles/salesforce-lightning-design-system-ltng.css" />

    <!-- Attributes -->
    <aura:attribute name="sObjectAPIName" type="String" required="false"
        description="The API name of the SObject to search" />
    <aura:attribute name="label" type="String" required="false"
        description="The label to assign to the lookup, eg: Account" />
    <aura:attribute name="pluralLabel" type="String" required="false"
        description="The plural label to assign to the lookup, eg: Accounts" />
    <aura:attribute name="listIconSVGPath" type="String" default="/resource/SLDSv0122/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." />

    <!-- 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/SLDSv0122/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/SLDSv0122/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/SLDSv0122/assets/icons/utility-sprite/svg/symbols.svg#search" />
                        &quot;{!v.searchString}&quot; in {!v.pluralLabel}
                    </button>
                </div>
                <ul aura:id="lookuplist-items" class="slds-lookup__list" role="presentation">
                </ul>
            </div>
        </div>
    </div>

</aura:component>

LookUpSobjectController.js :

({
    /**
     * 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);    
    }
})

LookUpSobjectHelper.js :

     ({
    /**
     * 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");
        var lookupListItems = cmp.find("lookuplist-items");

        // Clear any errors and destroy the old lookup items container
        inputElement.set('v.errors', null);
        lookupListItems.set('v.body', new Array());

        // 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();
                console.log('--matches---');
                console.log(matches);
                // If we have no matches, return
                if (matches.length == 0)
                {
                    return;
                }

                // Render the results
                this.renderLookupComponents(cmp, lookupListItems, 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);                
    },

    /**
     * Render the Lookup List Components
     */   
    renderLookupComponents : function(cmp, lookupListItems, matches)
    {
        // list Icon SVG Path and Class
        var listIconSVGPath = cmp.get('v.listIconSVGPath');
        var listIconClass = cmp.get('v.listIconClass');

        // Array of components to create
        var newComponents = new Array();

        // Add a set of components for each match found
        for (var i=0; i<matches.length; i++)
        {
            // li element
            newComponents.push(["aura:html", {
                "tag" : "li",
                "HTMLAttributes" : {
                    "class" : "slds-lookup__item"
                }
            }]);

            // a element
            newComponents.push(["aura:html", {
                "tag" : "a",
                "HTMLAttributes" : { 
                    "id" : cmp.getGlobalId() + '_id_' + matches[i].SObjectId, 
                    "role" : "option", 
                    "onclick" : cmp.getReference("c.select") 
                }
            }]);

            // svg component
            newComponents.push(["c:svg", {
                "class" : "slds-icon " + listIconClass + " slds-icon--small",
                "xlinkHref" : listIconSVGPath
            }]);

            // output text component
            // For some reason adding an aura:id to this component failed to record the id for subsequent cmp.find requests
            newComponents.push(["ui:outputText", {
                "value" : matches[i].SObjectLabel
            }]);
        }

        // Create the components
        $A.createComponents(newComponents, function(components, status) {
            // Creation succeeded
            if (status === "SUCCESS")
            {
                // Get the List Component Body
                var lookupListItemsBody = lookupListItems.get('v.body');

                // Iterate the created components in groups of 4, correctly parent them and add them to the list body
                for (var i=0; i<components.length; i+=4)
                {
                    // Identify the releated components
                    var li = components[i];
                    var a = components[i+1];
                    var svg = components[i+2];
                    var outputText = components[i+3];

                    // Add the <a> to the <li>
                    var liBody = li.get('v.body');
                    liBody.push(a);
                    li.set('v.body', liBody);

                    // Add the <svg> and <outputText> to the <a>
                    var aBody = a.get('v.body');
                    aBody.push(svg);
                    aBody.push(outputText);
                    a.set('v.body', aBody);

                    // Add the <li> to the container
                    lookupListItemsBody.push(li);
                }

                // Update the list body
                lookupListItems.set('v.body', lookupListItemsBody);
           }
           else // Report any error
           {
                this.displayToast('Error', 'Failed to create list components.');
           }
        });

    },

    /**
     * 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 2nd child (index 1)
        var objectLabel = event.currentTarget.children[1].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);
        }
    }
}) 

When used inside the app: lookup cmp, Working as expected

LookUp Inside app

When used in a page: lookup cmp, Not working

Inside VF page

9
  • Do you notice any errors in Javascript Console or in Developer Console Apex Logs?
    – Patlatus
    Feb 10, 2017 at 13:32
  • Also, have you tried to turn off Lightning Locker Security Update and if that might solve your issue?
    – Patlatus
    Feb 10, 2017 at 13:33
  • @Patlatus Thanks for reply, infact i am getting results i searched in lookup and that i can see in consle, And i think regarding locker service it will stay as critical update unless its new org, According to salesforce.stackexchange.com/questions/128688/…
    – SFDC_Igle
    Feb 10, 2017 at 14:35
  • so it is now unclear to me which issue do you face?
    – Patlatus
    Feb 10, 2017 at 14:39
  • @Patlatus Didnt understand that, i'm still trying for a luck on this
    – SFDC_Igle
    Feb 12, 2017 at 6:20

1 Answer 1

1

I was having similar issue where it would show "loading" icon when the component was embedded in VF page. See this post: force:inputField does not work in lightning component rendered on VF page

And to Itai's comment, please post concise code which will resolve it faster.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.