+ Start a Discussion
Internal PartnerInternal Partner 

Trailhead: Aura Components Basics / Connect Components with Events - The campingList component doesn't appear to have a Quantity input field in the form using a Lightning Base component

Hi all,

I am still stuck in this part of the module Aura Components Basics. I can not pass the challenge yet.
I have changed the code in campingList.cmp many times. This is the current version:
 
<aura:component controller="CampingListController">
    
    <aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
    <aura:handler name="addItem" event="c:addItemEvent" action="{!c.handleAddItem}"/>
    
    <div class="slds-page-header" role="banner">

      <div class="slds-grid">

        <div class="slds-col">

          <p class="slds-text-heading--label">Camping Items</p>

          <h1 class="slds-text-heading--medium">My Camping Items</h1>

        </div>

      </div>

    </div>

      
  <div aria-labelledby="newitemform">

      <fieldset class="slds-box slds-theme--default slds-container--small">
    
        <c:campingListForm />
    
      </fieldset>

    </div>
    
    
     <aura:attribute name="items" type="Camping_Item__c[]"/>

    <div class="slds-card slds-p-top--medium">
        <header class="slds-card__header">
            <h3 class="slds-text-heading--small">Camping List Items</h3>
        </header>
        
        <section class="slds-card__body">
            <div id="list" class="row">
                <aura:iteration items="{!v.items}" var="campItem">
                    <c:campingListItem item="{!campItem}"/>
                </aura:iteration>
            </div>
        </section>
    </div>

</aura:component>

But I am getting the error:
 
The campingList component doesn't appear to have a Quantity input field in the form using a Lightning Base component

Did somebody pass currently this challenge?
NagendraNagendra (Salesforce Developers) 
Hi,

Sorry for this issue you are facing.

May I suggest you please refer to below code using which I have cleared this module.
campingList.cmp:

<aura:component controller="CampingListController">
    
    <aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
    
    <aura:handler name="addItem" event="c:addItemEvent"
       action="{!c.handleAddItem }"/>
    <aura:attribute name="items" type="Camping_Item__c[]"/>
    <div class="slds-col slds-col--padded slds-p-top--large">

        <c:campingListForm />

    </div>
    <div class="slds-card slds-p-top--medium">
        <header class="slds-card__header">
            <h3 class="slds-text-heading--small">Items</h3>
        </header>
        
        <section class="slds-card__body">
            <div id="list" class="row">
                <aura:iteration items="{!v.items}" var="items">
                    <c:campingListItem newItem="{!items}"/>
                </aura:iteration>
            </div>
        </section>
    </div>

</aura:component>

campingListController.js:

({
    doInit: function(component, event, helper) {
    var action = component.get("c.getItems");
    action.setCallback(this, function(response) {
        var state = response.getState();
        if (component.isValid() && state === "SUCCESS") {
            component.set("v.items", response.getReturnValue());
        }
        else {
            console.log("Failed with state: " + state);
        }
    });
    $A.enqueueAction(action);
},

    
    handleAddItem: function(component, event, helper) {
    var action = component.get("c.saveItem");
            action.setParams({"item": newItem});
            action.setCallback(this, function(response){
                var state = response.getState();
                if (component.isValid() && state === "SUCCESS") {
                    // all good, nothing to do.
            var items = component.get("v.items");
            items.push(response.getReturnValue());
            component.set("v.items", items);
                }
            });
            $A.enqueueAction(action);
                }
})

campingListHelper.js:

({
   addItem: function(component, item) {
    this.saveItem(component, item, function(response){
        var state = response.getState();
        if (component.isValid() && state === "SUCCESS") {
        }
    });
},
})

campingListForm.cmp:

<aura:component >
    
    <aura:attribute name="newItem" type="Camping_Item__c"
                    default="{ 'sobjectType': 'Camping_Item__c',
                             'Name': '',
                             'Quantity__c': 0,
                             'Price__c': 0,
                             'Packed__c': false }"/>
    <aura:registerEvent name="addItem" type="c:addItemEvent"/>
    <form class="slds-form--stacked">
        
        <div class="slds-form-element slds-is-required">
            <div class="slds-form-element__control">
                <lightning:input aura:id="itemname" label="Name"
                                 class="slds-input"
                                 
                                 value="{!v.newItem.Name}"
                                 required="true"/>
                
            </div>
        </div>
        
        <div class="slds-form-element slds-is-required">
            <div class="slds-form-element__control">
                <p>Quantity:<lightning:input aura:id="itemform" name="Quantity" label="Quantity" value="{!v.newItem.Quantity__c}" 
                                             type="number" required="true" min="1" messageWhenRangeUnderflow="Enter minimum 1 Quantity"/>
                </p>
            </div>
        </div>
        
        <div class="slds-form-element">
            <div class="slds-form-element__control">
                <lightning:input aura:id="price" label="Price"
                                 class="slds-input"
                                 formatter="currency"
                                 value="{!v.newItem.Price__c}"
                                 />
            </div>
        </div>
        
        <div class="slds-form-element">
            <lightning:input aura:id="packed" label="Packed?"
                             class="slds-checkbox"
                             type="checkbox"
                             checked="{!v.newItem.Packed__c}" 
                             value="{!v.newItem.Packed__c}"/>
        </div>
        
        <div class="slds-form-element">
            <lightning:button label="Submit" 
                       class="slds-button slds-button--brand"
                       onclick="{!c.clickCreateItem}"/>
        </div>
        
    </form>
</aura:component>

campingListController.js:

({
    
    clickCreateItem : function(component, event, helper) {    
    if(helper.validateItemForm(component)){
        // Create the new item
        var newItem = component.get("v.newItem");
        helper.createItem(component, newItem);
    }
        },
    
    validateItemForm: function(component) {
        var validExpense = component.find('itemform').reduce(function (validSoFar, inputCmp) {
                        inputCmp.showHelpMessageIfInvalid();
                        return validSoFar && inputCmp.get('v.validity').valid;
                    }, true);

        return validExpense;
}
})

campingListFormHelper.js:

({
 addItem: function(component, newItem) {
    var addItem = component.getItem("addItem");
    addItem.setParams({ "item": item });
    addItem.fire();
            component.set("v.newItem",{ 'sobjectType': 'Camping_Item__c',
                    'Name': '',
                    'Quantity__c': 0,
                    'Price__c': 0,
                    'Packed__c': false });
},
    

        validateItemForm: function(component) {
        var validItem = true;

        var nameField = component.find("itemname");
        var itemname = nameField.get("v.value");
        if ($A.util.isEmpty(itemname)){
            validItem = false;
            nameField.set("v.errors", [{message:"Item name can't be blank."}]);
        }
        else {
            nameField.set("v.errors", null);
        }
        
        var quantityField = component.find("quantity");
        var quantity = nameField.get("v.value");
        if ($A.util.isEmpty(quantity)){
            validItem = false;
            quantityField.set("v.errors", [{message:"Quantity can't be blank."}]);
        }
        else {
            quantityField.set("v.errors", null);
        }
        var priceField = component.find("price");
        var price = priceField.get("v.value");
        if ($A.util.isEmpty(price)){
            validItem = false;
            priceField.set("v.errors", [{message:"Price can't be blank."}]);
        }
        else {
            quantityField.set("v.errors", null);
        }
            return (validItem);
    }
})

campingListItem.cmp:

<aura:component >
    <aura:attribute name="newItem" type="Camping_Item__c"
     default="{ 'sobjectType': 'Camping_Item__c',
                  'Name' : '',
                    'Quantity__c': 0,
                    'Price__c': 0
                     }" required="true"/>
    <p>Name:
        <ui:outputText value="{!v.item.Name}"/>
    </p>
    <p>Price:
        <lightning:formattedNumber value="{!v.item.Price__c}" style="currency"/>
    </p>
    <p>Quantity:<lightning:input aura:id="itemform" name="Quantity" label="Quantity" value="{!v.newItem.Quantity__c}" 
                    type="number" required="true" min="1" messageWhenRangeUnderflow="Enter minimum 1 Quantity"/>
    </p>
    <p>Packed:
        <lightning:input type="toggle" label="Packed?" checked="{!v.item.Packed__c}"/>
    </p>
    <div>
        <lightning:button label="Packed!" onClick="{!c.packItem}"/>
    </div>
</aura:component>

campingListItemController.js:

({
    packItem : function(component, event, helper) {
        var a = component.get("v.item", true);
        a.Packed__c=true;
        component.set("v.item", a); 
        var btn = event.getSource();
        btn.set("v.disabled",true);
    },
    
    validateItemForm: function(component) {
        var validExpense = component.find('itemform').reduce(function (validSoFar, inputCmp) {
                        inputCmp.showHelpMessageIfInvalid();
                        return validSoFar && inputCmp.get('v.validity').valid;
                    }, true);
        return validExpense;
}
})

addItemEvent.evt:

<aura:event type="COMPONENT">
    <aura:attribute name="item" type="Camping_Item__c"/>
</aura:event>
Hope this helps.

Kindly mark this as solved if the reply was helpful.

Thanks,
Nagendra