+ Start a Discussion
Shobhit SaxenaShobhit Saxena 

Trailhead challenge:"Connect components with Events"

The campingList JavaScript controller isn't setting the 'item' as a parameter or saving the record correctly.

My code is as follows:

1---Camping List Component
<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="newItem" type="Camping_Item__c"
     default="{ 'sobjectType': 'Camping_Item__c',
                    'Name': '',
                    'Quantity__c': 0,
                    'Price__c': 0,
                    'Packed__c': false }"/>
    
    <aura:attribute name="items" type="Camping_Item__c[]"/>
    
    <ol>
    <li>Bug Spray</li>
    <li>Bear Repellant</li>
    <li>Goat Food</li>
    </ol>
    
       <!-- NEW EXPENSE FORM -->
    <div class="slds-col slds-col--padded slds-p-top--large">

        <c:campingListForm/>

    </div>
    <!-- / NEW EXPENSE FORM -->    
   

    <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 item="{!item}"/>
                </aura:iteration>
            </div>
        </section>
    </div>

</aura:component>

2---Camping List Controller
 
({
    // Load 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 (component.isValid() && 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) {
    var newItem = event.getParam("item");
    //helper.createItem(component, newItem);
        this.saveItem(component, item, function(response){
        var state = response.getState();
        if (component.isValid() && state === "SUCCESS") {
            var items = component.get("v.items");
            items.push(response.getReturnValue());
            component.set("v.items", items);
        }
    }
          
}
                      
})

3---Camping List Helper

Empty

4---Camping List Form
 
<aura:component >
	
    <aura:registerEvent name="addItem" type="c:addItemEvent"/>
        <!-- CREATE NEW ITEM FORM -->
    <form class="slds-form--stacked">

      <div class="slds-form-element slds-is-required">
          <div class="slds-form-element__control">
              <ui:inputText aura:id="itemname" label="Name"
                  class="slds-input"
                  labelClass="slds-form-element__label"
                  value="{!v.newItem.Name}"
                  required="true"/>

          </div>
     </div>

     <div class="slds-form-element slds-is-required">
          <div class="slds-form-element__control">
              <ui:inputNumber aura:id="quantity" label="Quantity"
                  class="slds-input"
                  labelClass="slds-form-element__label"
                  value="{!v.newItem.Quantity__c}"
                  required="true"/>

          </div>
      </div>

      <div class="slds-form-element">
          <div class="slds-form-element__control">
              <ui:inputCurrency aura:id="price" label="Price"
                  class="slds-input"
                  labelClass="slds-form-element__label"
                  value="{!v.newItem.Price__c}"
                  />
          </div>
      </div>

      <div class="slds-form-element">
          <ui:inputCheckbox aura:id="packed" label="Packed?"
              class="slds-checkbox"
              labelClass="slds-form-element__label"
              value="{!v.newItem.Packed__c}"/>
      </div>

      <div class="slds-form-element">
          <ui:button label="Create Camping Item"
              class="slds-button slds-button--brand"
              press="{!c.clickCreateItem}"/>
      </div>

    </form>
    <!-- / CREATE NEW ITEM FORM -->
</aura:component>

5---CampingListFormController
 
({
    
    clickCreateItem: function(component, event, helper) {    
    if(helper.validateItemForm(component)){
        // Create the new item
        var newItem = component.get("v.newItem");
        helper.createItem(component, newItem);
    }
        
        }

})

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

		validateItemForm: function(component) {
		
              // Simplistic error checking
        var validItem = true;

        // Name must not be blank
        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);
        }
        
        // Quantity must not be blank
        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);
        }
		// Price must not be blank
        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;

	}
})

I am still getting this error:

User-added image

Any help would be appreciated.
 
Best Answer chosen by Shobhit Saxena
John Lay 9John Lay 9
See if this help for saving in the handleAddItem....
 
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.
        		}
    		});
    		$A.enqueueAction(action);

 

All Answers

John Lay 9John Lay 9
See if this help for saving in the handleAddItem....
 
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.
        		}
    		});
    		$A.enqueueAction(action);

 
This was selected as the best answer
Tavva Sai KrishnaTavva Sai Krishna
Hi Saxena,

Try replace this method with your's in CampaignListController method.
handleAddItem : function (component,event,helper){
			 var action = component.get("c.saveItem");
             var Item = event.getParam("item");
             var lstItems = component.get("v.items");
             console.log("Before:"+lstItems);
             lstItems.push(Item);
             component.set("v.items",lstItems);
             console.log("After:"+lstItems);
             action.setParams({"CampingItem":Item});
             action.setCallback(this,function(response){
                var state = response.getState();
                if (component.isValid() && state === "SUCCESS") {
                    console.log('save');
                }
             });
           $A.enqueueAction(action);   
        }

Let me know if still you are facing any issues.

Thanks and Regards,
Sai Krishna Tavva.
Guiomar Fernández de BobadillaGuiomar Fernández de Bobadilla
Hi,

I have the next error: The campingList JavaScript controller isn't adding the new record to the 'items' value provider

Here is my code: https://developer.salesforce.com/forums/ForumsMain?id=906F0000000kDmtIAE

It functions correctly, but the challenge isn't passed.
Shobhit SaxenaShobhit Saxena
Thank you @Tavva Sai Krishna and @John Lay 9, I've found a solution following your advice.

The code which worked for me is as follows:

@Guiomar Fernández de Bobadilla,you can try this piece of code:

(1) campingList Component
 
<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[]"/>
    
    <ol>
    <li>Bug Spray</li>
    <li>Bear Repellant</li>
    <li>Goat Food</li>
    </ol>
    
       <!-- NEW ITEM FORM -->
    <div class="slds-col slds-col--padded slds-p-top--large">

        <c:campingListForm />

    </div>
    <!-- / NEW ITEM FORM -->    
   

    <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 item="{!item}"/>
                </aura:iteration>
            </div>
        </section>
    </div>

</aura:component>

(2) campingListController
 
({
    // Load 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 (component.isValid() && 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) {
    //   var newItem = event.getParam("item");
    //helper.addItem(component, newItem);
    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);
        		}
    
              
})

(3) campingList Helper
 
({
   addItem: function(component, item) {
    this.saveItem(component, item, 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);*/
        }
    });
},
})

(4) campingListForm component
 
<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"/>
        <!-- CREATE NEW ITEM FORM -->
    <form class="slds-form--stacked">

      <div class="slds-form-element slds-is-required">
          <div class="slds-form-element__control">
              <ui:inputText aura:id="itemname" label="Name"
                  class="slds-input"
                  labelClass="slds-form-element__label"
                  value="{!v.newItem.Name}"
                  required="true"/>

          </div>
     </div>

     <div class="slds-form-element slds-is-required">
          <div class="slds-form-element__control">
              <ui:inputNumber aura:id="quantity" label="Quantity"
                  class="slds-input"
                  labelClass="slds-form-element__label"
                  value="{!v.newItem.Quantity__c}"
                  required="true"/>

          </div>
      </div>

      <div class="slds-form-element">
          <div class="slds-form-element__control">
              <ui:inputCurrency aura:id="price" label="Price"
                  class="slds-input"
                  labelClass="slds-form-element__label"
                  value="{!v.newItem.Price__c}"
                  />
          </div>
      </div>

      <div class="slds-form-element">
          <ui:inputCheckbox aura:id="packed" label="Packed?"
              class="slds-checkbox"
              labelClass="slds-form-element__label"
              value="{!v.newItem.Packed__c}"/>
      </div>

      <div class="slds-form-element">
          <ui:button label="Create Camping Item"
              class="slds-button slds-button--brand"
              press="{!c.submitForm}"/>
      </div>

    </form>
    <!-- / CREATE NEW ITEM FORM -->
</aura:component>

(5) campingListForm Controller
 
({
    
    submitForm: function(component, event, helper) {    
    if(helper.validateItemForm(component)){
        // Create the new item
        var newItem = component.get("v.newItem");
        helper.createItem(component, newItem);
    }
        
        }

})

(6) campingListForm Helper
 
({
 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) {
		
              // Simplistic error checking
        var validItem = true;

        // Name must not be blank
        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);
        }
        
        // Quantity must not be blank
        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);
        }
		// Price must not be blank
        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);

	}
})


(7) addItemEvent.evt
 
<aura:event type="COMPONENT">
    <aura:attribute name="item" type="Camping_Item__c"/>
</aura:event>

I hope it works for you ! :)
 
Guiomar Fernández de BobadillaGuiomar Fernández de Bobadilla
Hi,

I posted the solution yesterday in my discussion! (https://developer.salesforce.com/forums/ForumsMain?id=906F0000000kDmtIAE
)

Thank you anyway.
Jeff DouglasJeff Douglas
We just updated this module with some new code. Please try the challenge check again. Sorry for the inconvenience. 

Jeff Douglas
Trailhead Developer Advocate
Dennis PereverzevDennis Pereverzev
Encountered the same today.
My issue was in the name of newItem, just changed to item and all works.

campingListController.js
 
handleAddItem: function(component, event, helper) {
        var newItem = event.getParam("item");
        helper.createItem(component, newItem);
    }

changed to:
 
handleAddItem: function(component, event, helper) {
        var item = event.getParam("item");
        helper.createItem(component, item);
    }




 
Bao NVQBao NVQ
I still have the problem:
Challenge Not yet complete... here's what's wrong: 
The campingList JavaScript controller isn't setting the 'item' as a parameter or saving the record correctly.


Here is code of campingListController:
({	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 (component.isValid() && 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) {
        var item = event.getParam("item");

        helper.createItem(component, item);
    },
})
And code campingListHelper:
({
	createItem : function(component, item) {
		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(response.getReturnValue());
                component.set("v.items", items);
            }
        });
        $A.enqueueAction(action);
	}
})

The code ran well. I have checked. Why the challenger still not pass?
 
Akshay Deshmukh1Akshay Deshmukh1
Hello Everyone,

I also ran into this problem and read what challenge asks us to do line by line.

Trailhead challenge do not ask us to call HELPER method from campingListController.js. It just tells us to perform save action in campingListcontroller.js method instead. This is not very intuitive as trailhead module performs saving operation in HELPER method.

Just copy and past the code from campingListHelper.js to campingListController.js to pass the challenge. This is weird but this is how it is.

I hope this would help others.

Thanks,
Akshay
raj kiran 24raj kiran 24
Thanks @Akshay It worked without using helper method. strange but passed the challenege
Derek Bennett 5Derek Bennett 5
Anyone have any insight on this error message, im stuck

Challenge Not yet complete... here's what's wrong: 
The campingList JavaScript controller isn't calling the helper's 'createItem' function.
Derek Bennett 5Derek Bennett 5
camping list component wont save the code, it reads this error:

Failed to save undefined: No EVENT named markup://c:addItemEvent found : [markup://c:campinglist]: Source

Heres my code:
​<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[]"/>
    
    <ol>
    <li>Bug Spray</li>
    <li>Bear Repellant</li>
    <li>Goat Food</li>
    </ol>
    
       <!-- NEW ITEM FORM -->
    <div class="slds-col slds-col--padded slds-p-top--large">

        <c:campingListForm />

    </div>
    <!-- / NEW ITEM FORM -->    
   

    <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 item="{!item}"/>
                </aura:iteration>
            </div>
        </section>
    </div>

</aura:component>
Derek Bennett 5Derek Bennett 5
camping list component wont save the code, it reads this error:

Failed to save undefined: No EVENT named markup://c:addItemEvent found : [markup://c:campinglist]: Source

Heres my code:
​<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[]"/>
    
    <ol>
    <li>Bug Spray</li>
    <li>Bear Repellant</li>
    <li>Goat Food</li>
    </ol>
    
       <!-- NEW ITEM FORM -->
    <div class="slds-col slds-col--padded slds-p-top--large">

        <c:campingListForm />

    </div>
    <!-- / NEW ITEM FORM -->    
   

    <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 item="{!item}"/>
                </aura:iteration>
            </div>
        </section>
    </div>

</aura:component>
Guillaume Minero 8Guillaume Minero 8
Hi Derek, messsage states that you may have not created the EVENT named addItemEvent, can you valdiate?
Josh Gilliam 12Josh Gilliam 12
@Akshay Deshmukh1, your response just got me past the same problem.  Thank you SO MUCH for posting that.  I can't believe all the time I just spent trying to debug my code for this exercise, when the only problem was that I had split the save logic into a helper like the module demonstrated.  Ugh...  :-P
Akshay Deshmukh1Akshay Deshmukh1
@Josh Gilliam 12. Glad it helped solve your problem. :) 
Tim SHEINER 5Tim SHEINER 5
What @Akshay Deshmukh1 said, plus I had to add this line at the end of my handler
component.set("v.newItem", { 'sobjectType': 'Camping_Item__c',
    	'Packed__c': false, 'Name' : '', 'Quantity__c' : 0, 'Price__c' : 0} )

 
ramesh k 29ramesh k 29
Hi,
i copy your code but i an getting this error 

Challenge Not yet complete... here's what's wrong: 
The campingList JavaScript controller isn't calling the helper's 'createItem' function.
Drew Kennedy 7Drew Kennedy 7
Looking at Shobhit's code from 2016, there's no way that code would have worked - lots of bugs in the JavaScript are present.

A few things to note:
  • campingListForm Helper - line 2. getItem() isn't a function. You must use getEvent().
  • campingListFprm Helper - line 3. The variable item is being fed as a parameter, but it doesn't exist. The variable is brought in through the function, and is newItem.
  • The requirement is for the submit button to call the action submitForm

Here is code that worked:

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[]"/>
    
       <!-- NEW EXPENSE FORM -->
    <div class="slds-col slds-col--padded slds-p-top--large">
        <c:campingListForm/>
    </div>
    <!-- / NEW EXPENSE FORM -->    

    <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="item">
                    <c:campingListItem item="{!item}"/>
                </aura:iteration>
            </div>
        </section>
    </div>
</aura:component>

campingListController.js
 
({
    // Load 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 (component.isValid() && 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){
	var action = component.get("c.saveItem");
        var Item = event.getParam("item");
        var lstItems = component.get("v.items");

        lstItems.push(Item);
        component.set("v.items",lstItems);
        console.log("After:"+lstItems);
        action.setParams({"CampingItem":Item});
        action.setCallback(this,function(response){
            var state = response.getState();
                
            if (component.isValid() && state === "SUCCESS") {
                //let the magic happen
            }
         });
        $A.enqueueAction(action);   
     }
})

campingListHelper.js
({
    createCamping: function(component, item) {
        var theitems = component.get("v.items");
 
        var newitem = JSON.parse(JSON.stringify(item));
 
        theitems.push(newitem);
        component.set("v.items", theitems);
        
        component.set("v.newItem",{ 'sobjectType': 'Camping_Item__c','Name': '','Quantity__c': 0,
                    'Price__c': 0,'Packed__c': false });
    },
    validateCampingItem: function(component) {
        // Simplistic error checking
        var validCamping = true;

        // Name must not be blank
        var nameField = component.find("campname");
        
        if ($A.util.isEmpty(nameField.get("v.value"))){
            validCamping = false;
            nameField.set("v.errors", [{message:"Camping name can't be blank."}]);
        } else {
            nameField.set("v.errors", null);
        }
        
        if ($A.util.isEmpty(component.find("campQty").get("v.value"))){
            validCamping = false;
            component.find("campQty").set("v.errors", [{message:"Camping Quantity can't be blank."}]);
        } else {
            component.find("campQty").set("v.errors", null);
        }
        
        if ($A.util.isEmpty(component.find("campPrice").get("v.value"))){
            validCamping = false;
            component.find("campPrice").set("v.errors", [{message:"Camping Price can't be blank."}]);
        } else {
            component.find("campPrice").set("v.errors", null);
        }
        
        return(validCamping);
    },
    createItem: function(component, item) {
        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(response.getReturnValue());
                component.set("v.items", items);
            }
        });
            
        $A.enqueueAction(action);
    }
})

campingListForm.cmp
 
<aura:component >
    <aura:registerEvent name="addItem" type="c:addItemEvent"/>
    
    <aura:attribute name="newItem" type="Camping_Item__c"
     default="{ 'sobjectType': 'Camping_Item__c',
                    'Name': '',
                    'Quantity__c': 0,
                    'Price__c': 0,
                    'Packed__c': false }"/>
        <!-- CREATE NEW ITEM FORM -->
    <form class="slds-form--stacked">

      <div class="slds-form-element slds-is-required">
          <div class="slds-form-element__control">
              <ui:inputText aura:id="itemname" label="Name"
                  class="slds-input"
                  labelClass="slds-form-element__label"
                  value="{!v.newItem.Name}"
                  required="true"/>

          </div>
     </div>

     <div class="slds-form-element slds-is-required">
          <div class="slds-form-element__control">
              <ui:inputNumber aura:id="quantity" label="Quantity"
                  class="slds-input"
                  labelClass="slds-form-element__label"
                  value="{!v.newItem.Quantity__c}"
                  required="true"/>

          </div>
      </div>

      <div class="slds-form-element">
          <div class="slds-form-element__control">
              <ui:inputCurrency aura:id="price" label="Price"
                  class="slds-input"
                  labelClass="slds-form-element__label"
                  value="{!v.newItem.Price__c}"
                  />
          </div>
      </div>

      <div class="slds-form-element">
          <ui:inputCheckbox aura:id="packed" label="Packed?"
              class="slds-checkbox"
              labelClass="slds-form-element__label"
              value="{!v.newItem.Packed__c}"/>
      </div>

      <div class="slds-form-element">
          <ui:button label="Create Camping Item"
              class="slds-button slds-button--brand"
              press="{!c.submitForm}"/>
      </div>

    </form>
    <!-- / CREATE NEW ITEM FORM -->
</aura:component>

campingListFormController.js
 
({
    submitForm: function(component, event, helper) {    
        if(helper.validateItemForm(component)){
            // Create the new item
            var newItem = component.get("v.newItem");
            helper.createItem(component, newItem);
        }
    }
})

campingListFormHelper.js
 
({
	createItem: function(component, newItem) {
        var addItem = component.getEvent("addItem");
        addItem.setParams({ "item": newItem });
        addItem.fire();
        component.set("v.newItem",{ 'sobjectType': 'Camping_Item__c',
                        'Name': '',
                        'Quantity__c': 0,
                        'Price__c': 0,
                        'Packed__c': false });
    },
    validateItemForm: function(component) {
        // Simplistic error checking
        var validItem = true;

        // Name must not be blank
        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);
        }
        
        // Quantity must not be blank
        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);
        }
		// Price must not be blank
        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);
	}
})

And the event
 
<aura:event type="COMPONENT">
    <aura:attribute name="item" type="Camping_Item__c"/>
</aura:event>

Sorry for the indentation being wibbly-wobbly at times.
Arpit Vashishtha 7Arpit Vashishtha 7
Did anyone have faced this error in this trailhead: 
Challenge Not yet complete... here's what's wrong: 
The campingList component appears to be using UI Components instead of Base Lightning Components in the form. You should be using only Base Lightning Components.


CampingList.cmp:
<aura:component controller="CampingListController">
     <!--  <ol>
         <li>Bug Spray</li>
         <li>Bear Repellant</li>
         <li>Goat Food</li>
       </ol> -->
    <aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
    <aura:handler name="addItem" event="c:addItemEvent" action="{!c.handleAddItem}"/>

    <aura:attribute name="newItem" type="Camping_Item__c" required="true" default="{
                                                       'sobjectType': 'Camping_Item__c',
                                                          'Name': '',
                                                          'Quantity__c':0,
                                                           'Price__c':0,
                                                           'Packed__c':false }"/>

       <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-grid slds-m-top--large">

       <fieldset class="slds-box slds-theme--default slds-container--small">
            <legend id="newexpenseform1" class="slds-text-heading--small slds-p-vertical--medium">
          Camping List
         </legend>
              <section class="slds-card__body">
            <div id="list" class="row">
                <aura:iteration items="{!v.items}" var="item">
                    <c:campingListItem item="{!item}"/>
                </aura:iteration>
            </div>
        </section>
        </fieldset>
    </div>   
</aura:component>


Regards:
Arpit Vashishtha
Rakhi Rajput 2Rakhi Rajput 2
Yes!! Faced the same issue. 
Remove
<div class="slds-col slds-col--padded slds-p-top--large">
       <c:campingListForm/>
   </div>
and keep only 
 <c:campingListForm/>

Worked for me.
Arpit Vashishtha 7Arpit Vashishtha 7
Same Issue Rakhi Rajpur. after removing div.
Rob PisanoRob Pisano

I am also experiencing the issue "The campingList component appears to be using UI Components instead of Base Lightning Components in the form. You should be using only Base Lightning Components." 

Anyone able to find a workaround?

Faiza Naz 10Faiza Naz 10
Trailhead is changed a liltle more. you can find solution here.
http://faizanaz90.blogspot.com/2017/11/lightning-components-basics-connect-to.html
Sankeerth ReddySankeerth Reddy
Any one has the latest solution for it after they changed the module? 
Stalin CampusStalin Campus
Resolved this issue . Changed the code in CampingListForm . No need to change anything else. 

CampingListForm

<aura:component >
    <aura:registerEvent name="addItem" type="c:addItemEvent"/>
    
    <aura:attribute name="newItem" type="Camping_Item__c"
     default="{ 'sobjectType': 'Camping_Item__c',
                    'Name': '',
                    'Quantity__c': 1,
                    'Price__c': 0,
                    'Packed__c': false }"/>
        <!-- CREATE NEW ITEM FORM -->
    <form class="slsd-form--stacked">
            <lightning:input aura:id="campingform" label="Camping Name"
                                     name="campingname"
                                     value="{!v.newItem.Name}"
                                     required="true"/> 
                    <lightning:input type="number" aura:id="campingform" label="Quantity"
                                     name="campingQuantity"
                                     min="1"                                    
                                     step="1"
                                     value="{!v.newItem.Quantity__c}"
                                     messageWhenRangeUnderflow="Enter an Quantity that's at least 1."/>
                      <lightning:input type="number" aura:id="campingform" label="Price"
                                     name="campingPrice"
                                     min="0.1"
                                     formatter="currency"
                                     step="0.1"
                                     value="{!v.newItem.Price__c}"
                                     messageWhenRangeUnderflow="Enter an Price that's at least 0.1."/>
                    <lightning:input type="checkbox" aura:id="campingform" label="Packed ?"  
                                     name="campingPacked"
                                     checked="{!v.newItem.Packed__c}"/>
                    <lightning:button label="Create Camping" 
                                      class="slds-m-top--medium"
                                      variant="brand"
                                      onclick="{!c.clickCreateItem}"/>
        </form>
    <!-- / CREATE NEW ITEM FORM -->
</aura:component>
Arpit Vashishtha 7Arpit Vashishtha 7
That works... Thanks Stalin Campus.....(y)
Rajani PolampalliRajani Polampalli
Thanks Stalin.. That work's fine for me..
bheemudu neelibheemudu neeli
Getting below error to complete the challenge...
please help me to complete.
Challenge Not yet complete... here's what's wrong: 
The campingList component appears to be using UI Components instead of Base Lightning Components in the form. You should be using only Base Lightning Components.
BINOY MATHEWBINOY MATHEW
@Drew Kennedy and Stalin Campus- Got the challenge to pass by incorporarting your code but still after clicking Create Camping button it throws error that it doesn't recognize the clickCreateItem in campingListForm component. Its done as per the requirement in challenge.  Anyways thanks everyone for contributing. It does help.
Nirvik MitterNirvik Mitter
This worked for me; Here's a summary
(Do all the steps 1 to 8)

1. 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[]"/>
    
    <ol>
    <li>Bug Spray</li>
    <li>Bear Repellant</li>
    <li>Goat Food</li>
    </ol>
    
       <!-- NEW ITEM FORM -->
    <div class="slds-col slds-col--padded slds-p-top--large">

        <c:campingListForm />

    </div>
    <!-- / NEW ITEM FORM -->    
   

    <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 item="{!item}"/>
                </aura:iteration>
            </div>
        </section>
    </div>

</aura:component>
2. campingListController.js
({
    // Load 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 (component.isValid() && 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){
	var action = component.get("c.saveItem");
        var Item = event.getParam("item");
        var lstItems = component.get("v.items");

        lstItems.push(Item);
        component.set("v.items",lstItems);
        console.log("After:"+lstItems);
        action.setParams({"CampingItem":Item});
        action.setCallback(this,function(response){
            var state = response.getState();
                
            if (component.isValid() && state === "SUCCESS") {
                //let the magic happen
            }
         });
        $A.enqueueAction(action);   
     }
})

3. campingListForm.cmp
<aura:component >
    <aura:registerEvent name="addItem" type="c:addItemEvent"/>
    
    <aura:attribute name="newItem" type="Camping_Item__c"
     default="{ 'sobjectType': 'Camping_Item__c',
                    'Name': '',
                    'Quantity__c': 1,
                    'Price__c': 0,
                    'Packed__c': false }"/>
        <!-- CREATE NEW ITEM FORM -->
    <form class="slsd-form--stacked">
            <lightning:input aura:id="campingform" label="Camping Name"
                                     name="campingname"
                                     value="{!v.newItem.Name}"
                                     required="true"/> 
                    <lightning:input type="number" aura:id="campingform" label="Quantity"
                                     name="campingQuantity"
                                     min="1"                                    
                                     step="1"
                                     value="{!v.newItem.Quantity__c}"
                                     messageWhenRangeUnderflow="Enter an Quantity that's at least 1."/>
                      <lightning:input type="number" aura:id="campingform" label="Price"
                                     name="campingPrice"
                                     min="0.1"
                                     formatter="currency"
                                     step="0.1"
                                     value="{!v.newItem.Price__c}"
                                     messageWhenRangeUnderflow="Enter an Price that's at least 0.1."/>
                    <lightning:input type="checkbox" aura:id="campingform" label="Packed ?"  
                                     name="campingPacked"
                                     checked="{!v.newItem.Packed__c}"/>
                    <lightning:button label="Create Camping" 
                                      class="slds-m-top--medium"
                                      variant="brand"
                                      onclick="{!c.clickCreateItem}"/>
        </form>
    <!-- / CREATE NEW ITEM FORM -->
</aura:component>

4. campingListFormController.js
({
    
    submitForm: function(component, event, helper) {    
    if(helper.validateItemForm(component)){
        // Create the new item
        var newItem = component.get("v.newItem");
        helper.createItem(component, newItem);
    }
        
        }

})

5. campingListFormHelper.js
({
	createItem: function(component, newItem) {
        var addItem = component.getEvent("addItem");
        addItem.setParams({ "item": newItem });
        addItem.fire();
        component.set("v.newItem",{ 'sobjectType': 'Camping_Item__c',
                        'Name': '',
                        'Quantity__c': 0,
                        'Price__c': 0,
                        'Packed__c': false });
    },
    validateItemForm: function(component) {
        // Simplistic error checking
        var validItem = true;

        // Name must not be blank
        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);
        }
        
        // Quantity must not be blank
        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);
        }
		// Price must not be blank
        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);
	}
})

6. campingListController.apxc
public class CampingListController {
    @auraenabled
    public static List<Camping_Item__c> getItems (){
        List<Camping_Item__c> CI = [select id, name,price__c,Quantity__c,Packed__c from Camping_Item__c ];
        return CI;
    }
    @auraenabled
    public static Camping_Item__c saveItem (Camping_Item__c item){
        insert item;
        return item;
    }
}

7. campingListHelper.js
({
   addItem: function(component, item) {
    this.saveItem(component, item, 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);*/
        }
    });
},
})

8. addItemEvent.evt
<aura:event type="COMPONENT">
    <aura:attribute name="item" type="Camping_Item__c"/>
</aura:event>

   
I cleared the Trailhead Challenge - Lightning Components Basics - All of them; This piece above (Connect Components with Events > Refactor Components and Communicate with Events) was the last difficult hurdle.
Aldo NovaAldo Nova
Unknown controller action 'clickCreateItem' Failing descriptor: {markup://c:campingListForm}

...I think your createItem method should be clickCreateItem
Avinash YepuriAvinash Yepuri
I cleared the challenge witht the below code:

CampingApplication.app
<aura:application extends="force:slds" >
	<c:campingList />
</aura:application>
campingHeader.cmp
<aura:component >
    <lightning:layout class="slds-page-header slds-page-header--object-home">
    <lightning:layoutItem >
    <lightning:icon iconName="action:goal" alternativeText="My Camping"/>
</lightning:layoutItem>
    <lightning:layoutItem padding="horizontal-small">
<div class="page-section page-header">
<h1 class="slds-text-heading--label">Camping</h1>
<h2 class="slds-text-heading--medium">My Camping</h2>
</div>
</lightning:layoutItem>
</lightning:layout>
</aura:component>


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[]"/>
    <aura:attribute name="newItem" type="Camping_Item__c" default="{'Name':'',
    'Quantity__c':0,
    'Price__c':0,
    'Packed__c':false,
    'sobjectType':'Camping_Item__c'}"/>
    
    
 
<!-- NEW Campaing FORM -->
<div class="slds-col slds-col--padded slds-p-top--large">
 
 
<c:campingHeader/>
<div aria-labelledby="newCampaingForm">
 
<!-- BOXED AREA -->
<fieldset class="slds-box slds-theme--default slds-container--small">
 
<legend id="newCampaingForm" class="slds-text-heading--small
slds-p-vertical--medium">
Add Expense
</legend>

<div class="slds-col slds-col--padded slds-p-top--large">
    <c:campingListForm/>
</div>    
    
    
</fieldset>
<!-- / BOXED AREA -->
 
</div>
<!-- / CREATE NEW EXPENSE -->
</div>
<!-- ITERATIING ITEM LISTS -->
<div class="slds-card slds-p-top--medium">
 
<c:campingHeader/>
 
<section class="slds-card__body">
<div id="list" class="row">
<aura:iteration items="{!v.items}" var="item">
<c:campingListItem item="{!item}"/>
</aura:iteration>
</div>
</section>
</div>
<!-- / ITERATIING ITEM LISTS -->
</aura:component>

campingListController.js
({
    // Load items from Salesforce
    doInit: function(component, event, helper) {
			var action = component.get("c.getItems");
    	// Add callback behavior for when response is received
    		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);
        	}
    });
 // Send action off to be executed
    $A.enqueueAction(action);
},
handleAddItem: function(component, event, helper) {

    var action = component.get("c.saveItem");
        action.setParams({'item': event});
        action.setCallback(this, function(response){
            var state = response.getState();
            if(component.isValid() && state === "SUCCESS") {
                var items = component.get("v.items");
                items.push(response.getReturnValue());
               component.set("v.items", items); 
            }
        })
        $A.enqueueAction(action);
}
})
campingListForm.cmp
<aura:component >
    <aura:registerEvent name="addItem" type="c:addItemEvent"/>

	<form class="slds-form--stacked">
                        <lightning:input aura:id="campingform" label="Camping Item Name"
                         name="campingitemname"
                         value="{!v.newItem.Name}"
                         required="true"/>
                        <lightning:input type="number" aura:id="campingform" label="Quantity"
                         name="campingitemquantity"
                         min="1"
                         formatter="number"
                         step="0.1"
                         value="{!v.newItem.Quantity__c}"
                         messageWhenRangeUnderflow="Enter quantity that's at least 1."/>
      <lightning:input type="number" aura:id="campingform" label="Price"
                         name="campingitemprice"
                         min="0.1"
                         formatter="currency"
                         step="0.01"
                         value="{!v.newItem.Price__c}"
                         messageWhenRangeUnderflow="Enter an amount that's at least $0.10."/>
      <lightning:input type="checkbox" aura:id="campingform" label="Packed?" 
                         name="camingitempacked"
                         checked="{!v.newItem.Packed__c}"/>
       <lightning:button label="Create Camping" class="slds-m-top--medium"
                                 variant="brand" onclick="{!c.clickCreateItem}"/>
     </form>
</aura:component>
campingListFormController.js
({
	clickCreateItem: function(component, event, helper) {
        var validCamping = component.find('campingform').reduce(function (validSoFar, inputCmp) {
            // Displays error messages for invalid fields
            inputCmp.showHelpMessageIfInvalid();
            return validSoFar && inputCmp.get('v.validity').valid;
        }, true);
  	if(validCamping){
      // Create the new expense
            var newItem = component.get("v.newItem");
            console.log("Create item: " + JSON.stringify(newItem));
            helper.createItem(component, newItem);
        }

 }
})

campingListFormHelper.js
({
	createItem : function(component, item) {
		var createEvent = component.getEvent("addItem");
        createEvent.setParams({ "item": item });
        createEvent.fire();
        component.set("v.newItem",{ 'sobjectType': 'Camping_Item__c',
                    'Name': '',
                    'Quantity__c': 0,
                    'Price__c': 0,
                    'Packed__c': false });
}
})
campingListItem.cmp
<aura:component >
<aura:attribute name="item" type="Camping_Item__c"/>
 
Name:
<ui:outputText value="{!v.item.Name}"/>
 
Price:
<ui:outputCurrency value="{!v.item.Price__c}"/>
 
Quantity:
<ui:outputNumber value="{!v.item.Quantity__c}"/>
 
Packed:
<ui:outputCheckbox value="{!v.item.Packed__c}"/>
 
</aura:component>


CampingListController.apxc
public with sharing class CampingListController {
	@AuraEnabled
    public static List<Camping_Item__c> getItems() {
        // Perform isAccessible() checking first, then
        return [SELECT Id, Name, Quantity__c, Price__c,
                       Packed__c, CreatedDate 
                FROM Camping_Item__c];
    }
    
    @AuraEnabled
    public static Camping_Item__c saveItem(Camping_Item__c item) {
        // Perform isUpdatable() checking first, then
        upsert item;
        return item;
    }
}

addItemEvent.evt
 
<aura:event type="COMPONENT">
    <aura:attribute name="item" type="Camping_Item__c"/>
</aura:event>




 
Harsha vardhan 170Harsha vardhan 170
@avinashyepuru code worked for me 
Prudhvi MuppallaPrudhvi Muppalla
I'm able to complete the challenge with below code. Please like it if it works for you.
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[]"/>

<c:campingListForm />

<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="item">
                <c:campingListItem item="{!item}"/>
            </aura:iteration>
        </div>
    </section>
</div>
</aura:component>

campingListController.js
({
    doInit : function(component, event, helper){
        var getCampingItemListingAction = component.get('c.getItems');
        getCampingItemListingAction.setCallback(this, function(response){
            var respState = response.getState();
            if(respState == 'SUCCESS'){
                var vItems = component.get('v.items');
                vItems = response.getReturnValue();
                component.set('v.items', vItems);
            }
        });
        $A.enqueueAction(getCampingItemListingAction);
    },
    handleAddItem : function(component, event, helper){
        var newCampingItem = event.getParam('item');

        //var theItems = component.get("v.items");
        //theItems.push(newCampingItem);
        //component.set("v.items", theItems);

        //helper.createItem(component, newCampingItem);
        var saveItemAction = component.get('c.saveItem');
        saveItemAction.setParams({ 'campingItem' :  newCampingItem });

        saveItemAction.setCallback(this, function(response){
            var respState = response.getState();
            console.log(respState);
            if( respState == 'SUCCESS'){
                var theItems = component.get("v.items");
                theItems.push(response.getReturnValue());
                component.set("v.items", theItems);
            }
        });

        $A.enqueueAction(saveItemAction);
    }
})

campingListHelper.js
({
   
    createItem : function(component, campaign) {
        var action = component.get("c.saveItem");
        action.setParams({
            "item": campaign
        });
        action.setCallback(this, function(response){
            var state = response.getState();
            if (state === "SUCCESS") {
                var expenses = component.get("v.items");
                expenses.push(response.getReturnValue());
                component.set("v.items", expenses);
            }
        });
        $A.enqueueAction(action);
    },
})
campingListForm.cmp
<aura:component controller="CampingListController">
<aura:registerEvent name="addItem" type="c:addItemEvent" />

<aura:attribute name="newItem" type="Camping_Item__c"
 default="{ 'sobjectType': 'Camping_Item__c',
                'Name': '',
                'Quantity__c': 0,
                'Price__c': 0,
                'Packed__c': false }" required="true"/>

<!-- CREATE NEW ITEM FORM -->
<form class="slds-form--stacked">

  <div class="slds-form-element slds-is-required">
      <div class="slds-form-element__control">
          <lightning:input aura:id="campingItem" type="text" name="name" label="Name" value="{!v.newItem.Name}" required="true" />
      </div>
 </div>

 <div class="slds-form-element slds-is-required">
      <div class="slds-form-element__control">
          <lightning:input aura:id="campingItem" type="number" label="Quantity" name="quantity" value="{!v.newItem.Quantity__c}" step="1" min="1" required="true" />
      </div>
  </div>

  <div class="slds-form-element">
      <div class="slds-form-element__control">
          <lightning:input aura:id="campingItem" type="number" formatter="currency" name="price" label="Price" value="{!v.newItem.Price__c}"  />
      </div>
  </div>

  <div class="slds-form-element">
      <lightning:input aura:id="campingItem" type="checkbox" label="Packed?" name="packed" checked="{!v.newItem.Packed__c}" />
  </div>

  <div class="slds-form-element">
      <lightning:button label="Create Camping Item" onclick="{!c.clickCreateItem}" />
  </div>

</form>
<!-- / CREATE NEW ITEM FORM -->
</aura:component>
campingListFormController.js
({
    myAction : function(component, event, helper) {

    },
    clickCreateItem: function(component, event, helper) {

        // Simplistic error checking
        var validItem = true;
        validItem = component.find('campingItem').reduce(function(validSoFar, inputCmp){
            inputCmp.showHelpMessageIfInvalid();
            return validSoFar && inputCmp.get('v.validity').valid;
        }, true);

        if(validItem){
            helper.createItem(component);
        }
    }
})

campingListFormHelper.js
({
    helperMethod : function() {

    },
    createItem : function(component){

        var campingItem = component.get("v.newItem");
        console.log(campingItem);

        var adItemEvent = component.getEvent('addItem');
        adItemEvent.setParams({'item': campingItem});
        adItemEvent.fire();
        component.set("v.newItem",{'sobjectType':'Camping_Item__c',
                'Name': '',
                'Quantity__c': 0,
                'Price__c': 0,
                'Packed__c': false});
        console.log('Event fired');
    }
})

addItemEvent.evt
<aura:event type="COMPONENT">
    <aura:attribute name="item" type="Camping_Item__c"/>
</aura:event>

 
Pankaj VishwakarmaPankaj Vishwakarma
Thanks  @Nirvik Mitter, your code worked fine 
viksit rana 2viksit rana 2
This is Apex controller for this Challenge 
Apex class CampingListController  
public with sharing class CampingListController {

    @AuraEnabled 
    public static List<Camping_Item__c> getItems() {
        return [SELECT Id, Name, Price__c, Quantity__c, Packed__c FROM Camping_Item__c];
    }
    
    @AuraEnabled
    public static Camping_Item__c saveItem(Camping_Item__c item) {
        upsert item;
        return item;
    }
}
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[]"/>
    
    <ol>
    <li>Bug Spray</li>
    <li>Bear Repellant</li>
    <li>Goat Food</li>
    </ol>
    
       <!-- NEW ITEM FORM -->
    <div class="slds-col slds-col--padded slds-p-top--large">

        <c:campingListForm />

    </div>
    <!-- / NEW ITEM FORM -->    
   

    <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 item="{!item}"/>
                </aura:iteration>
            </div>
        </section>
    </div>

</aura:component>
CampingListController.js
({
    // Load 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 (component.isValid() && 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) {
    //   var newItem = event.getParam("item");
    //helper.addItem(component, newItem);
    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") {
            // all good, nothing to do.
         /*   var items = component.get("v.items");
            items.push(response.getReturnValue());
            component.set("v.items", items);*/
        }
    });
},
})

CampingListForm.cmp
<aura:component >
    <aura:registerEvent name="addItem" type="c:addItemEvent"/>
    
    <aura:attribute name="newItem" type="Camping_Item__c"
                    default="{ 'sobjectType': 'Camping_Item__c',
                             'Name': '',
                             'Quantity__c': 1,
                             'Price__c': 0,
                             'Packed__c': false }"/>
    <!-- CREATE NEW ITEM FORM -->
    <form class="slsd-form--stacked">
        <lightning:input aura:id="campingform" label="Camping Name"
                         name="campingname"
                         value="{!v.newItem.Name}"
                         required="true"/> 
        <lightning:input type="number" aura:id="campingform" label="Quantity"
                         name="campingQuantity"
                         min="1"                                    
                         step="1"
                         value="{!v.newItem.Quantity__c}"
                         messageWhenRangeUnderflow="Enter an Quantity that's at least 1."/>
        <lightning:input type="number" aura:id="campingform" label="Price"
                         name="campingPrice"
                         min="0.1"
                         formatter="currency"
                         step="0.1"
                         value="{!v.newItem.Price__c}"
                         messageWhenRangeUnderflow="Enter an Price that's at least 0.1."/>
        <lightning:input type="checkbox" aura:id="campingform" label="Packed ?"  
                         name="campingPacked"
                         checked="{!v.newItem.Packed__c}"/>
        <lightning:button label="Create Camping" 
                          class="slds-m-top--medium"
                          variant="brand"
                          onclick="{!c.clickCreateItem}"/>
    </form>
    <!-- / CREATE NEW ITEM FORM -->
</aura:component>

CampingListFormController.js
({
    
    submitForm: function(component, event, helper) {    
    if(helper.validateItemForm(component)){
        // Create the new item
        var newItem = component.get("v.newItem");
        helper.createItem(component, newItem);
    }
        
        }

})

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) {
		
              // Simplistic error checking
        var validItem = true;

        // Name must not be blank
        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);
        }
        
        // Quantity must not be blank
        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);
        }
		// Price must not be blank
        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);

	}
})
addItemEvent.evt
<aura:event type="COMPONENT">
    <aura:attribute name="item" type="Camping_Item__c"/>
</aura:event>

CampingApp.app​​​​​​​
<aura:application extends="force:slds">
    <c:campingHeader />
    <c:campingList />
</aura:application>



 
Matt HolmesMatt Holmes
@viksit rana 2 

In your handleAddItem function were are you getting the newItem variable? your code has it commented out.
handleAddItem: function(component, event, helper) {
    //   var newItem = event.getParam("item");
    //helper.addItem(component, newItem);
    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);
        		}
    
              
})

 
Mohit AhujaMohit Ahuja
@vikshit rana ur code is the latest one...worked for me...thanku so much
Shashi Mogalgiddi 3Shashi Mogalgiddi 3
@Nirvik Mitter, thanks for your steps 1 to 8.  I tried all other option but your steps finally worked.  Even though this is obsolete, just wanted to pass the test and move on.
Yogesh MeltyYogesh Melty
This code worked for me to pass the challenge.
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[]"/>
    <c:campingListForm/>
    <div>
    <aura:iteration items="{!v.items}" var="item">
        <c:campingListItem item="{!item}"/> 
    </aura:iteration>
    </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(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({
            "items": items
        });
        action.setCallback(this, function(response){
            var state = response.getState();
            if (state === "SUCCESS") {
                var items = component.get("v.items");
                items.push(response.getReturnValue());
                component.set("v.items", items);
            }
        });
        $A.enqueueAction(action);
    },
})


CampingListHelper.js
({
    createItem: function(component, items) {
        var action = component.get("c.saveItem");
        action.setParams({
            "items": items
        });
        action.setCallback(this, function(response){
            var state = response.getState();
            if (state === "SUCCESS") {
                var items = component.get("v.items");
                items.push(response.getReturnValue());
                component.set("v.items", items);
            }
        });
        $A.enqueueAction(action);
    },
})


CampingListController.apxc
public class CampingListController 
{
    public static List<Camping_Item__c> getItems()
    {
        return[SELECT Name, Quantity__c, Price__c, Packed__c from Camping_Item__c];
    }
	public static Camping_Item__c saveItem(Camping_Item__c items)
    {
        upsert items;
        return items;
    }
}


campingListForm.cmp
<aura:component >
    <aura:registerEvent name="addItem" type="c:addItemEvent"/>
    <aura:attribute name="newItem" type="Camping_Item__c"
         default="{ 'sobjectType': 'Camping_Item__c',
                        'Name': '',
                        'Quantity__c': 0,
                        'Price__c': 0,
                        'Packed__c': ''}"/>
	<div aria-labelledby="newcampingform">
        <fieldset class="slds-box slds-theme--default slds-container--small">
  
        <form class="slds-form--stacked">          
            <lightning:input aura:id="campingform" label="Name"
                             name="name"
                             value="{!v.newItem.Name}"
                             required="true"/> 
            <lightning:input type="number" aura:id="campingform" label="Quantity"
                             name="quantity"
                             min="1"
                             formatter="Number"
                             step="1"
                             value="{!v.newItem.Quantity__c}"
                             messageWhenRangeUnderflow="Enter a quantity that's at least 1."/>
            <lightning:input aura:id="campingform" label="Price"
                             name="price"
                             formatter="currency" 
                             value="{!v.newItem.Price__c}"
                             />
            <lightning:input type="checkbox" aura:id="campingform" label="Packed"  
                             name="packed"
                             checked="{!v.newItem.Packed__c}"/>
            <lightning:button label="Create Item" 
                              class="slds-m-top--medium"
                              variant="brand"
                              onclick="{!c.clickCreateItem}"/>
        </form>
      </fieldset>
    </div>
</aura:component>


campingListFormController.js
({
	handleAdditem: function(component, event, helper) {
        var newItem = event.getParam("items");
        helper.createItem(component, items);
    }
})


campingListFormHelper.js
({
	 createItem: function(component, items) {
        var createEvent = component.getEvent("addItem");
        createEvent.setParams({ "items": items });
        createEvent.fire();
        component.set("v.newItem",{'sobjectType':'Camping_Item__c',
                'Name': '',
                'Quantity__c': 0,
                'Price__c': 0,
                'Packed__c': false});
    }
})

addItemEvent.evt
<aura:event type="COMPONENT">
    <aura:attribute name="item" type="Camping_Item__c"/>
</aura:event>

 
om mamidwarom mamidwar

campingListForm.cmp

<aura:component >
    <aura:registerEvent name="addItem" type="c:addItemEvent"/>
    
    <aura:attribute name="newItem" type="Camping_Item__c"
     default="{ 'sobjectType': 'Camping_Item__c',
                    'Name': '',
                    'Quantity__c': 0,
                    'Price__c': 0,
                    'Packed__c': false }"/>
        <!-- CREATE NEW ITEM FORM -->
    <form class="slds-form--stacked">
      <lightning:input aura:id="itemform" 
                       label="Name"
                       name="itemname"
                       value="{!v.newItem.Name}"
                       required="true"/>

      <lightning:input type="number" 
                       aura:id="itemform" 
                       label="Quantity"
                       name="quantity"
                       value="{!v.newItem.Quantity__c}"
                       min="1"
                       required="true"/>

      <lightning:input type="number" 
                       aura:id="itemform" 
                       label="Price"
                       name="price"
                       value="{!v.newItem.Price__c}"
                       formatter="currency"
                       step="0.01"/>

      <lightning:input type="checkbox" 
                       aura:id="itemform" 
                       label="Packed?"
                       name="packed"
                       checked="{!v.newItem.Packed__c}"/>

      <lightning:button label="Create Camping Item"
                        variant="brand"
                        onclick="{!c.clickCreateItem}"/>
</form>
    

   
    <!-- / CREATE NEW ITEM FORM -->
</aura:component>
GOURISHETTY SAIRAMGOURISHETTY SAIRAM
Hi all , these codes worked perfectly for me.
After many hours of struggle :)


campingListForm.cmp
<aura:component >
    <aura:registerEvent name="addItem" type="c:addItemEvent"/>
    
    <aura:attribute name="newItem" type="Camping_Item__c"
     default="{ 'sobjectType': 'Camping_Item__c',
                    'Name': '',
                    'Quantity__c': 1,
                    'Price__c': 0,
                    'Packed__c': false }"/>
        <!-- CREATE NEW ITEM FORM -->
    <form class="slsd-form--stacked">
            <lightning:input aura:id="campingform" label="Camping Name"
                                     name="campingname"
                                     value="{!v.newItem.Name}"
                                     required="true"/> 
                    <lightning:input type="number" aura:id="campingform" label="Quantity"
                                     name="campingQuantity"
                                     min="1"                                    
                                     step="1"
                                     value="{!v.newItem.Quantity__c}"
                                     messageWhenRangeUnderflow="Enter an Quantity that's at least 1."/>
                      <lightning:input type="number" aura:id="campingform" label="Price"
                                     name="campingPrice"
                                     min="0.1"
                                     formatter="currency"
                                     step="0.1"
                                     value="{!v.newItem.Price__c}"
                                     messageWhenRangeUnderflow="Enter an Price that's at least 0.1."/>
                    <lightning:input type="checkbox" aura:id="campingform" label="Packed ?"  
                                     name="campingPacked"
                                     checked="{!v.newItem.Packed__c}"/>
                    <lightning:button label="Create Camping" 
                                      class="slds-m-top--medium"
                                      variant="brand"
                                      onclick="{!c.clickCreateItem}"/>
        </form>
    <!-- / CREATE NEW ITEM FORM -->
</aura:component>

campingListHelper.js
({
	
    validateFields : function (component,field) {
        
        var nameField = field;
        console.log('yes:'+nameField);
        var expname = nameField.get("v.value"); 
        if ($A.util.isEmpty(expname)){
           component.set("v.er",true);
           nameField.set("v.errors", [{message:"this field can't be blank."}]);
        }
        else {
            nameField.set("v.errors", null);
        }
    },
    
    createItem : function (component,Item){         
        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 campings = component.get("v.items");
                campings.push(response.getReturnValue());
                component.set("v.items", campings);
            }
        });
       $A.enqueueAction(action);        
    }
})


campingListController.apxc
public with sharing class CampingListController {

    @AuraEnabled 
    public static List<Camping_Item__c> getItems() {
        return [SELECT Id, Name, Price__c, Quantity__c, Packed__c FROM Camping_Item__c];
    }
    
    @AuraEnabled
    public static Camping_Item__c saveItem(Camping_Item__c item) {
        upsert item;
        return item;
    }
}


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 item = event.getParam("item");
                
        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);
    }
    
})

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}"/>
    
    <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>


campingListItemController.js
({
	packItem: function(component, event, helper) {
        var newMessage = event.getSource().get("v.label");
        console.log("handleClick2: Message: " + newMessage);
        component.set("v.item.Packed__c", true);
        component.set("v.packed!",disabled="true");
    },
})

addItemEvent.evt
<aura:event type="COMPONENT" description="Event template" >
<aura:attribute name="item" type="Camping_Item__c"/>
</aura:event>