[SalesForce] Lightning/Aura components: access to the component attributes

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?

Best Answer

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.

Related Topic