5

Argh! Pulling my hair out! I am new to Lightning and I have an app that takes a list Contacts names and phone numbers and allows the user to "Check them in". There is a component that receives and displays all the checked in contacts. I have "Check In" button to pass them to component and it's not successfully passing the contacts. I know this because while the list of items is incrementing I cannot get the contact name to list.

Here is the list component:

<aura:component controller="xsp.ContactController">

<aura:attribute name="contacts" type="xsp.Contact[]"/>
<aura:handler event="xsp:SearchKeyChange" action="{!c.searchKeyChange}"/>
<aura:registerEvent name="selectContactEvent" type="xsp:selectContact"/>

<ul class="list-group">
    <aura:iteration items="{!v.contacts}" var="contact">
        <li class="list-group-item">
            <p>{!contact.Name}</p>
            <p>{!contact.Phone}</p>
        <a href="#" onclick="{!c.checkIn}" class="btn btn-primary"> Check-In</a>
        </li>
    </aura:iteration>
</ul>

Here is the controller:

({
    doInit : function(component, event) {
        var action = component.get("c.findAll");
        action.setCallback(this, function(a) {
            component.set("v.contacts", a.getReturnValue());
        });
        $A.enqueueAction(action);
    },
    searchKeyChange: function(component, event) {
    var searchKey = event.getParam("searchKey");
    var action = component.get("c.findByName");
    action.setParams({
      "searchKey": searchKey
    });
    action.setCallback(this, function(a) {
        component.set("v.contacts", a.getReturnValue());
    });
    $A.enqueueAction(action);
    },
    checkIn : function(component, event, helper) {
       var contact = component.get("v.contact");
       var evt = $A.get("e.xsp:selectContact");
       evt.setParams({
        "contact": contact
       });
       evt.fire();
    },
})

Here is the event:

<aura:event type="APPLICATION" description="Select contact event.">  
    <aura:attribute name="contact" type="Contact"/>
</aura:event>

Here is the receiving component:

<aura:component >  
    <aura:attribute name="items" type="xsp.Contact[]"/>
    <aura:handler event="xsp:selectContact" action="{!c.handleCheckInEvent}"/>

    <div class="col-lg-9 col-md-9 col-sm-12">
        <div class="col-lg-12 col-sm-12">
            <span class="title">Check-in List:</span>
        </div>
        <aura:renderIf isTrue="{!v.items.length > 0}">
        <div class="col-lg-12 col-sm-12 hero-feature">
            <table class="table table-bordered tbl-cart">
                <thead>
                    <tr>
                        <td>Name</td>
                        <td class="hidden-xs">Room Number</td>
                    </tr>
                </thead>
                <tbody>
                    <aura:iteration items="{!v.items}" var="item">
                    <tr>
                        <td>{!item.Name}</td>
                        <td class="hidden-xs">
                        </td>
                    </tr>
                    </aura:iteration>
                </tbody>
            </table>

        </div>
        </aura:renderIf>
        <aura:renderIf isTrue="{!v.items.length == 0}">
            <div class="col-lg-12 col-sm-12 hero-feature">
                <p>    Nobody is checked in yet.</p>
            </div>
        </aura:renderIf>
    </div>
</aura:component>

Controller:

({
    handleCheckInEvent : function(component, event, helper) {
        var contact = event.getParam("contact");
        var items = component.get("v.items");
        if (!items) items = []; 
        items.push(contact);
        component.set("v.items", items);
    },
})
3

Alternatively to Martin's suggestion, you can also create a secondary component to display the Contact itself and create an attribute to pass that component which you can then reference via the client side controller of the secondary component with the component.get('v.VARIABLENAME') functionality.

This structure lends itself better to projects that are very modular, leaning towards many micro components versus larger components (much like meteor.js/blaze templating is done).

Main Contact List Component

<aura:attribute name="contacts" type="xsp.Contact[]"/>
<aura:handler event="xsp:SearchKeyChange" action="{!c.searchKeyChange}"/>

<ul class="list-group">
    <aura:iteration items="{!v.contacts}" var="contact">
        <li class="list-group-item">
            <xsp:contactView contact="{!contact}"/>
        </li>
    </aura:iteration>
</ul>

Here the code is very similar, but the view for the contact is pushed to a secondary component with an attribute for the contact to pass through. The client side controller is the same, except the checkIn method is moved to the second components controller.

Individual Contact View Component (called as xsp:contactView in list component)

<aura:component>
    <aura:attribute name="contact" type="xsp.Contact"/>
    <aura:registerEvent name="selectContactEvent" type="xsp:selectContact"/>

  <p>{!v.contact.Name}</p>
  <p>{!v.contact.Phone}</p>
  <ui:outputText click="{!c.checkIn}"> Check-In</ui:outputText>
  <!-- only using ui:outputText cause I know it from top of head, but you could use any of the aura components that have click method AFAIK -->
</ul>

This component declares an attribute to collect the contact which can pass through the component now and be used as a variable. Interesting note, I put registerEvent here, but you could also leave it at the parent component, as long as one of them declares it, it will function.

xsp:contactView Client Side Controller

({
    checkIn : function(component, event, helper) {
       var contact = component.get("v.contact");
       var evt = $A.get("e.xsp:selectContact");
       evt.setParams({
        "contact": contact
       });
       evt.fire();
    },
})

Same code as before, except now contact is actually exposed via the v. prefix. The third component receiving the event would receive an event handler with a contact passed through.

Note: I just restructured your code, haven't tested, so there might be dragons in here still

2

It looks like the problem is related to accessing the contact in the iteration. Since there isn't an attribute named contact on the component, the variable set to component.get("v.contact") will be undefined. To access the contact you selected, you could set an index variable on the iteration, get that index through the event, and then use that index to get the contact from the component attribute contacts.

Set up index variable

<ul class="list-group">
    <aura:iteration items="{!v.contacts}" var="contact" indexVar="index">
        <li class="list-group-item">
            <p>{!contact.Name}</p>
            <p>{!contact.Phone}</p>
        <a href="#" onclick="{!c.checkIn}" data-index="{!index}" class="btn btn-primary">Check-In</a>
        </li>
    </aura:iteration>
</ul>

Use index to get contact from list

checkIn : function(component, event, helper) {
    var contactList = component.get("v.contacts");
    var index = event.target.attributes.getNamedItem("data-index").value;
    var contact = contactList[index];
    var evt = $A.get("e.xsp:selectContact");
    evt.setParams({
        "contact": contact
    });
    evt.fire();
},
0

Actually you have to follow component based development approach here. I've given a link, where i'm breaking account list component and passing the account data in each iteration to another component called account card.

https://github.com/shankar-ray/jlightningdeveloper/tree/master/metadata/aura

Then, inside account card i'm firing the event.

This way you'd get account id and then, once you have the id, do anything you could possibly imagine. In your case it would be contact and instead of account, hope it helps.

Watch my playlist on lightning to understand the event model, where i'm displaying list of cases on account selection event. Remember it's all about events.

https://www.youtube.com/playlist?list=PL2-SrZjAI-uSwSNYYYXwUIzjlBBioJRJa

Hope it helps.

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.