2

I was successfully loading a static resource into a Lightning component using the following ltng:require:

<ltng:require scripts="{!$Resource.SObjectSearchBar}" afterScriptsLoaded="{!c.createAndSetSearchbar}"/>

I split the Component in question into an extendable super component and a sub component. When the ltng:require is on the super component it runs no problem. When it's on the sub component it never runs the afterScriptsLoaded.

There's no error in my browser's console, the Salesforce developer console, nor on the page that uses the component. The network tab in my browser's console show's that it's at least getting to the static resource in Salesforce.

I've done some extensive googling, tried fiddling around with the way it calls the script, the location (super vs. sub component) of the afterScriptsLoaded method, calling the static resource via Aura, adding a ltng:require to both components, and I'm no closer to an answer. Any help would be greatly appreciated.

Parent Component (SObjectSearchbar)

HTML:

<aura:component extensible="true">  

<aura:attribute name="searchbar" type="Object"/>
<aura:attribute name="SObjectSearchBar" type="Object"/>
<aura:attribute name="query" type="String" default=""/>
<aura:attribute name="intervalRunning" type="Boolean" default="false"/>
<aura:attribute name="extendInterval" type="Boolean" default="false"/>

<aura:attribute name="placeholder" type="String" default="- Please Select an Option -" />
<aura:attribute name="actionName" type="String" />
<aura:attribute name="SObject" type="String" />

<aura:handler event="c:SObjectSelected" action="{!c.updateFilter}"/> 
<aura:handler event="c:ClearSObjectSelection" action="{!c.handleClear}"/> 
<aura:registerEvent name="SObjectSelected" type="c:SObjectSelected"/>
<aura:registerEvent name="ClearSObjectSelection" type="c:ClearSObjectSelection"/>

<div style="position:relative">
    <ui:inputText placeholder="{!v.placeholder}" click="{!c.toggleDropdown}" keydown="{!c.searchSObjectList}" class="searchbarInput" value="{!v.searchbar.query}"/>
    <div aura:id="dropdown" class="slds-dropdown-trigger slds-dropdown-trigger_click searchbarInput searchbarDropdown slds-scrollable__x">
      <div class="slds-dropdown slds-dropdown_left slds-dropdown_length-7" style="width:20rem" onscroll="{!c.loadMoreResults}">
        <ul class="slds-dropdown__list" role="menu">
        <aura:iteration items="{!v.searchbar.displayList}" var="obj">
          <li class="slds-dropdown__item" role="presentation" > 
            <a href="javascript:void(0);" role="menuitem" tabindex="0">
              <span onclick="{!c.selectSObject}" title="{!obj.Name}" id="{!obj.salesforceId}">{!obj.searchableData}</span>
            </a>
          </li>
        </aura:iteration>
        </ul>
      </div>
    </div>
</div>
</aura:component>

Controller:

({
toggleDropdown : function(component, event, helper){
    helper.toggleDropdown(component);
},   

loadMoreResults : function(component, event, helper){
    var searchbar = component.get('v.searchbar');
    var scrollTop = event.srcElement.scrollTop;
    var scrollHeight = event.srcElement.scrollHeight;
    var clientHeight = event.srcElement.clientHeight;
    if(searchbar.pointer < searchbar.sobjectList.length && !searchbar.scrollLock && scrollHeight - scrollTop <= (clientHeight + 25)){
        helper.loadResults(component, searchbar);
    }
},

searchSObjectList : function(component, event, helper){
    helper.clearSelectedId(component);
    helper.fireClearSObjectSelection(component);
    var searchbar = component.get('v.searchbar');
    var pressedKey = event.Ob.domEvent.key;
    if(pressedKey.length == 1){
        searchbar.query += pressedKey;
    }
    else{
        searchbar.query = '';
    }
    if(component.get('v.intervalRunning')){
        component.set('v.extendInterval', true);
    }
    else{
        component.set('v.intervalRunning', true);
        window.setTimeout($A.getCallback(function(){helper.runInterval(component, helper)}), 500);
    }   
},

selectSObject : function(component, event, helper){
    helper.updateSelectedId(component, event);
    helper.toggleDropdown(component);
    helper.fireSObjectSelected(component);
},

updateFilter : function(component, event, helper){

},

handleClear : function(component, event, helper){

}
})

Helper:

({
createSearchbar : function (component) {
    var searchbar = {sobjectList : [],
                     displayList : [],
                     displayIncrement : 15,
                     query : "",
                     pointer : 0,
                     selected : "",
                     scrollLock : false
                    };      
    component.set("v.searchbar", searchbar);
    component.set('v.SObjectSearchBar', new SObjectSearchBar());
    console.log('searchbar');
    console.log(searchbar);
},

getSObjects : function (component, action) { 
    action.setCallback(this,function(response){this.getSObjectsCallback(response,component);});
    $A.enqueueAction(action);   
},

getSObjectsCallback : function(response,component){
    if (response.getState() === "SUCCESS") {
        var returnValue = response.getReturnValue();
        if(returnValue){
            var searchbar = component.get("v.searchbar");
            searchbar.sobjectList = returnValue;
            var SObjectSearchBar = component.get("v.SObjectSearchBar");
            searchbar = SObjectSearchBar.incrementDisplayList(searchbar);
            component.set("v.searchbar", searchbar);
        }
    } else if (response.getState() === "ERROR") {
        console.log('initializeAccount failure');
        $A.log("Errors", response.getError());
    }
},

toggleDropdown : function(component){
    var dropdownId = component.get('v.dropdownId');
    var searchbarDropdown = component.find(dropdownId);
    $A.util.toggleClass(searchbarDropdown, 'slds-is-open');
},   

loadResults : function(component, searchbar){
    searchbar.scrollLock = true;
    var SObjectSearchBar = component.get('v.SObjectSearchBar');
    searchbar = SObjectSearchBar.incrementDisplayList(searchbar);
    component.set('v.searchbar', searchbar);
},

runInterval : function(component, helper){
    var searchbar = component.get('v.searchbar');
    if(component.get('v.extendInterval')){
        component.set('v.extendInterval', false);
        window.setTimeout($A.getCallback(function(){helper.runInterval(component, helper)}), 500);

    }
    else{
        searchbar = this.performSearch(component, searchbar);
        component.set('v.intervalRunning', false);
    }
    component.set('v.searchbar', searchbar);        
},

performSearch : function(component, searchbar){
    var SObjectSearchBar = component.get('v.SObjectSearchBar');
    searchbar.displayList = [];
    searchbar.pointer = 0;
    searchbar = SObjectSearchBar.incrementDisplayList(searchbar);       
    return searchbar;
},

updateSelectedId : function(component, event){
    var searchbar = component.get('v.searchbar');
    var selectedId = event.srcElement.id;
    var selectedName = event.srcElement.title;
    searchbar.query = selectedName;
    searchbar.selected = selectedId;
    component.set('v.searchbar', searchbar);
},

clearSelectedId : function(component){
    var searchbar = component.get('v.searchbar');
    searchbar.selected = '';
    component.set('v.searchbar', searchbar);
}z

fireSObjectSelected : function(component){
    var sobject = component.get('v.SObject');
    var searchbar = component.get('v.searchbar');
    var selectedId = searchbar.selectedId;

    var action = $A.get('e.c:SObjectSelect');
    action.setParams({'sobjectType' : sobject, 'salesforceId' : selectedId});
    action.fire();
},

fireClearSObjectSelection : function(component){
    var sobject = component.get('v.SObject');
    var action = $A.get('e.c:ClearSObjectSelection');
    action.setParams({'sobjectType' : sobject});
    action.fire();
}
})

Child Component (AccountSearchbar)

HTML:

<aura:component controller="AccountSearchbarController" extends="c:SObjectSearchbar" >  
    <ltng:require scripts="{!$Resource.SObjectSearchBar}" afterScriptsLoaded="{!c.createAndSetSearchbar}"/>
</aura:component>

Controller:

createAndSetSearchbar : function(component, event, helper){
    console.log('sub');
    helper.createSearchbar(component);

    var action = component.get('c.getSearchbarAccounts');   
    helper.getSObjects(component, action);        
},

Static Resource:

window.SObjectSearchBar = function() {
var incrementDisplayList = function(searchbar) {
    var sobjectList = searchbar.sobjectList;
    var displayList = searchbar.displayList;
    var displayIncrement = searchbar.displayIncrement;
    var query = searchbar.query;
    var pointer = searchbar.pointer;
    var addedSObjects = 0;
    var matchesQuery;
    while(pointer < sobjectList.length && addedSObjects < displayIncrement){    
        if(!query){
            matchesQuery = true;
        }   
        else{
            matchesQuery = this.searchTermsInData(sobjectList[pointer].searchableData, query);
        }   

        if(matchesQuery){
            displayList.push(sobjectList[pointer]); 
            addedSObjects++;                
        }       
        pointer++;  
    }
    searchbar.displayList = displayList;
    searchbar.pointer = pointer;
    searchbar.scrollLock = false;
    return searchbar;
};

var searchTermsInData = function(searchableData, query) {
    var searchTerms = query.split(" ");
    for (var searchTerm of searchTerms){
        if(!searchableData.toLowerCase().includes(searchTerm.toLowerCase())){
            return false;                
        }
    }
    return true;
};

var getSObjectFromList = function(sobjectList, sobjectID){
    for(var i in sobjectList){
        if(sobjectList[i].salesforceId == sobjectID){
            return sobjectList[i];
        }
    }
    return null;
};

return{
    incrementDisplayList : incrementDisplayList,
    searchTermsInData : searchTermsInData,
    getSObjectFromList : getSObjectFromList
};

}

  • 1
    Not sure if I have an answer for you yet, but would like to see more code. Ideally most of the relevant pieces of both components – Sebastian Kessel Jun 26 '17 at 20:54
  • I've added more of the code. Please let me know if you need more information. Thanks for the response! – Ryan Dinesman Jun 26 '17 at 21:08
  • Are these classes on the parent or the child component? Also, What about the markup of both parent and child? – Sebastian Kessel Jun 26 '17 at 21:11
  • The helper methods are in the parent component. The controller method has been in just the parent component, just the child component, both components at the same time, nothing has worked. The child had only the component tags (with a server side controller) and the ltng:require tag. There was quite a bit more in the parent component, but it never had any issues. The rest of the HTML rendered properly regardless of the static resource. I can post it if you'd like, not sure how helpful it'll be though. – Ryan Dinesman Jun 26 '17 at 21:19
  • Ryan, I am not sure I follow. The more code you post, the better. – Sebastian Kessel Jun 26 '17 at 21:20

Your Answer

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

Browse other questions tagged or ask your own question.