4

I am trying to dynamically create a picklist in a lightning component which aligns with the lightning design system look and feel. The lightning design system says that we should create it as given in link below.

https://www.lightningdesignsystem.com/components/menus/#flavor-picklist

I want to add list item elements from the helper on the fire of init method. I am receiving these items as a response of an apex controller call from the helper. However, when I am trying to modify the innerHTML of the list and add the response items as list items it is not rendering them.

I am doing it like

    var action = component.get(ApexCall);
    var self = this;
    action.setCallback(this, function(actionResult) {

        var family=actionResult.getReturnValue();
        var famLength=family.length;
        var listDOM = document.getElementById("familyList");
        var j= listDOM.innerHTML;
        j=j+'<li id="menu-40-0" class="slds-dropdown__item"> <a href="javascript:void(0);" role="menuitemradio"> <p class="slds-truncate">';
        j=j+'<c:svg ariaHidden="true" class="slds-icon slds-icon--selected slds-icon--x-small slds-icon-text-default slds-m-right--x-small" xlinkHref="/assets/icons/utility-sprite/svg/symbols.svg#check"/>'; 
        j=j+family[0]+'</p> </a> </li>"';

Could anyone tell me how to make it work?

1 Answer 1

4

In Lightning I would be much more inclined to create this list through an aura:iteration at the component markup level, bound to an array that you can set, rather than appending strings to innerHTML. However if you still want to do it this way...

The innerHTML property is a string, not a reference. You are assigning it to a variable, building it up and then never sending it back. (Unless you have left out part of your code?) So try...

    var family=actionResult.getReturnValue();
    var famLength=family.length;
    var listDOM = document.getElementById("familyList");
    var j= '';
    j=j+'<li id="menu-40-0" class="slds-dropdown__item"> <a href="javascript:void(0);" role="menuitemradio"> <p class="slds-truncate">';
    j=j+'<c:svg ariaHidden="true" class="slds-icon slds-icon--selected slds-icon--x-small slds-icon-text-default slds-m-right--x-small" xlinkHref="/assets/icons/utility-sprite/svg/symbols.svg#check"/>'; 
    j=j+family[0]+'</p> </a> </li>"';
    listDOM.innerHTML += j;

Also if you are not familiar with the shorthand increment/concatenation operator +=, in JavaScript j = j + (expression) can be written more compactly as j += (expression).

Also be aware that inserting c:svg into the markup is probably not going to work because Lightning XML is converted to scripted elements at the server level and not at the browser level.

So what would a more data-based Lightning solution look like? Well in your markup you could have something like:

<aura:attribute name="family" type="String[]" />

<ul>
    <aura:iteration items="{!v.family}" var="item">
        <li class="slds-dropdown__item">
           <a href="javascript:void(0);" role="menuitemradio">
               <p class="slds-truncate">
                   <c:svg ariaHidden="true" class="slds-icon slds-icon--selected slds-icon--x-small slds-icon-text-default slds-m-right--x-small" xlinkHref="/assets/icons/utility-sprite/svg/symbols.svg#check"/>
               {!item}
               </p>
           </a>
        </li>
    </aura:iteration>
</ul>

And then your controller would simply populate the array:

component.set('v.family', actionResult.getReturnValue());

Or merge the new items into an existing array, creating a new one if none is there:

var family = component.get('v.family') || [];
var newFamily = family.concat(actionResult.getReturnValue());
component.set('v.family', newFamily);
2
  • Thank you so much Charles. I realized the mistake in my design right after i posted this and shifted to aura:iteration. Worked perfect. However, the issue I am facing now is that I need the get the value of that {!item} on click of each <li>. Any idea how I can make that happen? I am not being able to do that since I don't have an ID and i guess lightning doesn't allow parameters on a client side controller. Commented Jun 17, 2016 at 5:41
  • Good question... one possibility is to assign an index variable as well (so <aura:iteration items="{!v.family}" var="item" indexvar="index">) and then tag the list item with a data attribute such as <li class="slds-dropdown__item" data-index="{!index}">. Your handler can then peek into the event and get the index out as e.target.dataset.index. Under Lightning Locker this works as long as the element was created in your namespace. (Not sure if there is a better way to pass up a parameter...)
    – Charles T
    Commented Jun 17, 2016 at 13:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .