+ Start a Discussion
Sumanta Mukherjee 14Sumanta Mukherjee 14 

Lightning trailhead solution for Event - Error "The campingList component isn't iterating the array of 'items' and creating 'campingListItem' components."

While working on the trailhead challenge "Connect Components with Events" I am getting this error - "The campingList component isn't iterating the array of items and creating campingListItem components."
Here is my code.

Thanks.
1) campingItem.app
<aura:application extends="force:slds">
    <c:campingHeader/>	
</aura:application>
2) campingHeader.cmp
<aura:component>
    <!-- PAGE HEADER -->
    <lightning:layout class="slds-page-header slds-page-header--object-home">
        <lightning:layoutItem>
            <lightning:icon iconName="action:goal" alternativeText="Camping Items"/>
        </lightning:layoutItem>
        <lightning:layoutItem padding="horizontal-small">
            <div class="page-section page-header">
                <h1 class="slds-text-heading--label">Camping Items</h1>
                <h2 class="slds-text-heading--medium">New Camping Items</h2>
            </div>
        </lightning:layoutItem>
    </lightning:layout>
    <!-- / PAGE HEADER -->
    <!-- NEW EXPENSE FORM -->
    <lightning:layout>
        <lightning:layoutItem padding="around-small" size="6">
        <!-- [[ expense form goes here ]] -->
            <c:campingList/>
        </lightning:layoutItem>
    </lightning:layout>
    <!-- / NEW EXPENSE FORM -->
</aura:component>

3) campingList.cmp
<aura:component controller="CampingListController">
    <aura:attribute name="items" type="Camping_Item__c[]"/>
 
    <aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
    
    <aura:handler name="addItem" event="c:addItemEvent" action="{!c.handleAddItem}"/>
	
    <!--Call campingListForm component for new Item Entry Form-->
    <c:campingListForm/>
	
    <!-- /Creating a list of items -->
    <lightning:card title="Items">
        <p class="slds-p-horizontal--small">
            <aura:iteration items="{!v.items}" var="campingItem">
                <c:campingListItem campingItem="{!campingItem}"/>
            </aura:iteration>
        </p>
    </lightning:card>
	
</aura:component>

4) campingListController.js
({
  
    // Load camping items from Salesforce
    doInit: function(component, event, helper) {
        // Create the action
        var action = component.get("c.getItems");
        // Add callback behavior for when response is received
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                component.set("v.items", response.getReturnValue());
            }
            else {
                console.log("Failed with state: " + state);
            }
        });
        // Send action off to be executed
        $A.enqueueAction(action);
    },
    
    handleAddItem: function(component, event, helper) {
        
        component.set("v.newItem",
                     { 'sobjectType': 'Camping_Item__c',
                    'Name': '',
                    'Packed__c': false,
                    'Price__c': 0,
                    'Quantity__c': 0});
    }
})
5) campingListItem.cmp
<aura:component>
    <aura:attribute name="campingItem" type="Camping_Item__c"/>
    <lightning:card title="{!v.campingItem.Name}" iconName="action:goal"
                    class="{!v.campingItem.Packed__c ?
                           'slds-theme--success' : ''}">
        <p class="slds-text-heading--medium slds-p-horizontal--small">
           Price: <lightning:formattedNumber value="{!v.campingItem.Price__c}" style="currency"/>
        </p>
        <p class="slds-text-heading--medium slds-p-horizontal--small">
           Quantity: <lightning:formattedNumber value="{!v.campingItem.Quantity__c}" style="decimal"/>
        </p>
        <p>
            <lightning:input type="toggle" 
                             label="Packed?"
                             name="packed"
                             class="slds-p-around--small"
                             checked="{!v.campingItem.Packed__c}"
                             messageToggleActive="Yes"
                             messageToggleInactive="No"
                             onchange="{!c.clickPacked}"/>
        </p>
    </lightning:card>
</aura:component>

6) campingListForm.cmp
<aura:component controller="CampingListController">
    <aura:attribute name="items" type="Camping_Item__c[]"/>
    <aura:attribute name="newItem" type="Camping_Item__c"
         default="{ 'sobjectType': 'Camping_Item__c',
                        'Name': '',
                        'Quantity__c': 0,
                        'Price__c': 0,
                        'Packed__c': false }"/>
   
    <aura:handler name="init" action="{!c.doInit}" value="{!this}"/>

    <aura:registerEvent name="addItem" type="c:addItemEvent"/>

    <!-- CREATE NEW CAMPING ITEM -->
    <div aria-labelledby="newitemform">
        <!-- BOXED AREA -->
        <fieldset class="slds-box slds-theme--default slds-container--small">
        <legend id="newitemform" class="slds-text-heading--small 
          slds-p-vertical--medium">
          Add New Camping Item
        </legend>
  
        <!-- CREATE NEW CAMPING ITEM FORM -->
        <form class="slds-form--stacked">          
            <lightning:input aura:id="newitemform" label="Camping Item Name"
                             name="itemname"
                             value="{!v.newItem.Name}"
                             required="true"/> 
            <lightning:input type="number" aura:id="newitemform" label="Price"
                             name="itemprice"
                             min="0.1"
                             formatter="currency"
                             step="0.01"
                             value="{!v.newItem.Price__c}"
                             messageWhenRangeUnderflow="Enter a price that's at least $0.10."/>
            <lightning:input type="number" aura:id="newitemform" label="Quantity"
                             name="itemquantity"
                             min="1"
                             step="1"
                             value="{!v.newItem.Quantity__c}" 
                             messageWhenRangeUnderflow="Enter a quantity that's greater than 0."/>
            <lightning:input type="checkbox" aura:id="newitemform" label="Packed?"  
                             name="itempacked"
                             checked="{!v.newItem.Packed__c}"/>
            <lightning:button label="Create New Item" 
                              class="slds-m-top--medium"
                              variant="brand"
                              onclick="{!c.submitForm}"/>
        </form>
        <!-- / CREATE NEW CAMPING ITEM FORM -->
  
      </fieldset>
      <!-- / BOXED AREA -->
    </div>
    <!-- / CREATE NEW CAMPING ITEM -->
</aura:component>

7) campingListFormController.js​​​​​​​
​​​​​​​
({
    //Create new camping item
	submitForm : function(component, event, helper) {
        
        var isFormValid = component.find("newitemform").reduce(function(validSoFar, inputCmp){
            // Displays error messages for invalid fields
        	inputCmp.showHelpMessageIfInvalid();    	
            return validSoFar && inputCmp.get("v.validity").valid;
        });
        
        if (isFormValid) {
            
            var newCampingItem = component.get("v.newItem");
            helper.createItem(component, newCampingItem);
           
        }
	}
})
8) campingListFormHelper.js
({
     createItem : function(component) {
                       
        var action = component.get("c.saveItem");
        action.setParams({
            "item": item
        });
        
        action.setCallback(this, function(response){
            var state = response.getState();
            if (component.isValid() && state === "SUCCESS") {        
                var items = component.get("v.items");
                items.push(item);
                component.set("v.items",items);
            }
        });
        $A.enqueueAction(action);
         
        var item = event.getParam("item");
        var newItem = component.get("v.newItem");
        var addEvent = component.getEvent("addItem");
        addEvent.setParams({"item" : newItem});
        addEvent.fire();
        /*component.set("v.newItem",
                     { 'sobjectType': 'Camping_Item__c',
                    'Name': '',
                    'Packed__c': false,
                    'Price__c': 0,
                    'Quantity__c': 0});*/
    }
    
    
})
9) campingListController.apxc
public with sharing class CampingListController {
    @AuraEnabled
    public static List<Camping_Item__c> getItems() {
		List<Camping_Item__c> campingItems = [SELECT Id,Name,Price__c,Packed__c,Quantity__c FROM Camping_Item__c];
        return campingItems;
    }
    
    @AuraEnabled
    public static Camping_Item__c saveItem(Camping_Item__c campingItem) {
        upsert campingItem;
        return campingItem;
    }
}

10) addItemEv​​​​​​​ent.evt​​​​​​​​​​​​​​​​​​​​​​​​​​​​
<aura:event type="COMPONENT">
    <aura:attribute name="item" type="Camping_Item__c"/>
</aura:event>

​​​​​​​
NagendraNagendra (Salesforce Developers) 
Hi Sumanta,

Sorry for this issue you are facing.

I faced a similar issue in the past. Note that the attribute name on the campingListItem component of 'campingItem' - I named this differently to ensure not everything was just named 'item' - kinda made more sense to me to do it that way. However, Trailhead expects that it will find an attribute named "item", so the correct (passing) code is:
<lightning:card> <aura:set attribute="title"> Camping Items </aura:set> <p class="slds-p-horizontal--small"> <aura:iteration var="item" items="{!v.items}" > <c:campingListItem item="{!item}"/> </aura:iteration> </p>
Naturally, everything in the campingListItem component had to be changed to reflect the new attribute name also...

Hope this helps.

Kindly mark this as solved if the reply was helpful.

Thanks,
Nagendra
Akshay GuptaAkshay Gupta
Hi Nagendra, your tip helped me.
Thank you