5

I'm trying to build a super simple app where I have a list of Item and I can select them, and see the selected in a second list.

I have tried to setup a simple aura component:

<aura:component controller="MyApexControllerWithAuraEnabled">

    <aura:attribute name="items" type="Item__c[]"/>
    <aura:attribute name="itemsSelected" type="Item__c[]"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />

    <div class="col-md-8">
        <ul onchange="{!c.change}">
            <aura:iteration items="{!v.items}" var="p">
                <li class="item-li" onclick="{!c.select}">{!p.Name}</li>
            </aura:iteration>
        </ul>
    </div>

    <div class="col-md-4">
        <ul onchange="{!c.change}">
            <aura:iteration items="{!v.itemsSelected}" var="p">
                <li class="item-li">{!p.Name}</li>
            </aura:iteration>
        </ul>
    </div>
</aura:component>

In the controller, with doInit function I ask for Items__c object from Salesforce. When run the app, I see them, and it is good.

Now I want that, when a clik happen on a element, a new li element with same name appears also in the second list. But I don't manage to do it.

I have tried (inside the select function that is correctly called):

    var action = component.get("v.items");
    action.setCallback(this, function(response) {
        console.log('**** ',response);
    });
    $A.enqueueAction(action);

But nothing is showed. I can retrive them from apex adding this code to my client controller:

    var action = component.get("c.getItemByName");
    action.setParams({
      "name": event.target.innerHTML
    });
    action.setCallback(this, function(a) {
        console.log('get back from server:', a.returnValue);
    });
    $A.enqueueAction(action);

But then I don't know how to add it to the itemSelected and I think it is a useless because I should already have that elements in the client.

Any advice please?

1 Answer 1

10

This example loads items on the client-side and captures the selected text value in the DOM. See the next example to capture the selected text value on the object itself.

<aura:component>
    <aura:attribute name="list" type="String[]" default="Item 1, Item 2, Item 3"/>
    <aura:attribute name="selected" type="String[]"/>

    <ul>
    <aura:iteration items="{!v.list}" var="l">
        <li><ui:outputText value="{!l}" click="{!c.select}"/></li>
    </aura:iteration>
    </ul>

    <ul>
        <aura:iteration items="{!v.selected}" var="s">
            <li><ui:outputText value="{!s}"/></li>
        </aura:iteration>
    </ul>
</aura:component>

Notice that I'm using a ui:outputText component instead of letting the li element handle the click event. If you use this component, you can easily retrieve its value using the get("v.value") syntax.

({
    select : function(component, event, helper) {
        console.log("selected");
        var src = event.getSource();
        var name = src.get("v.value");
        component.set("v.selected", name);
    }
})

When you click an li element, the second list updates with the name of the element you clicked. I'm not sure if this satisfies your use case but hope the example helps!

Update: The following example uses an event to capture the selected item and its fields (including name etc).

<!----- list.cmp 
  Assumes you are loading contact items in an Apex controller
----->
<aura:component controller="ContactController">
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <aura:attribute name="contacts" type="Contact[]"/>
    <aura:attribute name="selected" type="Contact[]"/>

    <!-- Handle the Click Event -->
    <aura:handler event="c:selectContact" action="{!c.getContact}" />

    <ul>
    <aura:iteration items="{!v.contacts}" var="contact">
        <li><c:listItem contact="{!contact}" /></li>
    </aura:iteration>
    </ul>

    <ul>
        <aura:iteration var="contact" items="{!v.selected}">
            <c:listItem contact="{!contact}"/>
        </aura:iteration>
    </ul>
</aura:component>

/* listController.js 
    Load the contacts in an init handler and
    append the name of the selected item to the 'selected' string array
*/
({
    doInit : function(component, event, helper) {
        helper.getContacts(component);
    },

    getContact : function(component, event, helper) {
       var selected = event.getParam("contact");
        console.log(selected);
        var arr = component.get("v.selected");
        arr.push(selected);
        component.set("v.selected", arr);
    }
})

/* listHelper.js
    Return all contact records and
    display them in the UI 
 */
({
    getContacts : function(cmp) {
        // Load all contact data
        var action = cmp.get("c.getContacts");
        var self = this;
        action.setCallback(this, function(response){
            var state = response.getState();
            if (state === "SUCCESS") {
                cmp.set("v.contacts", response.getReturnValue());
            }
            else {
                alert("something has gone wrong");
            }
        });
     $A.enqueueAction(action);
    }
})

<!----- listItem.cmp 
    The contact item
----->
<aura:component>
    <aura:attribute name="contact" type="Contact"/>
    <ui:outputText value="{!v.contact.Name}" click="{!c.select}"/>
</aura:component>

/* listItemController.js 
    Fire the select event to communicate the contact item
*/
({
    select : function(component, event, helper) {
         var contact = component.get("v.contact");
        console.log("contact: " + contact);
        var selectEvent = $A.get("e.c:selectContact");
        selectEvent.setParams({ "contact": contact }).fire();
    },
})

<!----- selectContact.evt 
    The event containing the contact object
----->
<aura:event type="APPLICATION">
    <aura:attribute name="contact" type="Contact"/>
</aura:event>

Or grab the example at https://gist.github.com/dianawidjaja/8c644af14f2ea23d4f31.

4
  • Thanks for aswer it. So.. First of all, it seems to me that you overwrite the selected list, not add the element to it. Then, you are getting from event source only the value that is a rendered string. This is kind of a fake. I need to access to the original Item__c object: at least the SFDC id of it. Not only a rendered string. In Angular terminology I need to access to the $scope (saying that you list and selected are inside the $scope)... not only the rendererd things.
    – mcmc
    Commented Apr 28, 2015 at 9:41
  • You can use a component event to capture the item that's selected and display that item. Please have a look at gist.github.com/dianawidjaja/8c644af14f2ea23d4f31. This sample code returns the selected item as an object. Commented Apr 28, 2015 at 16:37
  • Thanks. Works like a charm. Please add the gist to the answer and I will accept is as correct.
    – mcmc
    Commented Apr 29, 2015 at 16:43
  • These two examples are the most concise examples I have seen re: moving from client side component to client side controller in lightning. Thanks for the post @DianaWidjajaMyerscough . Commented May 21, 2015 at 13:31

You must log in to answer this question.

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