You need to sign in to do that
Don't have an account?

Stuck in trailhead - Lightning Components Basics
Challenge - Create a form to enter new items and display the list of items entered. To make our camping list look more appealing, change the campingHeader component to use the SLDS. Similar to the unit, style the Camping List H1 inside the slds-page-header. Modify the campingList component to contain an input form and an iteration of campingListItem components for displaying the items entered.
The component requires an attribute named items with the type of an array of camping item custom objects.
The component requires an attribute named newItem of type Camping_Item__c with default quantity and price values of 0.
The component displays the Name, Quantity, Price, and Packed form fields with the appropriate input component types and values from the newItem attribute.
The JavaScript controller checks to ensure that the Name, Quantity and Price values submitted are not null.
If the form is valid, the JavaScript controller pushes the newItem onto the array of existing items, triggers the notification that the items value provider has changed, and resets the newItem value provider with a blank sObjectType of Camping_Item__c.
My answer -
<aura:component >
<aura:attribute name="items" type="Camping_Item__c[]"/>
<aura:attribute name="newitem" type="Camping_Item__c[]" default="{ 'sobjectType': 'Camping_Item__c',
'Quantity__c'=0, 'Price__c'=0}"/>
<p>Name:
<ui:inputText value="{!v.newitem.name}"/>
</p>
<p>Packed:
<ui:inputCheckbox value="{!v.newitem.Packed__c}"/>
</p>
<p>Price:
<ui:inputCurrency value="{!v.newitem.Price__c}"/>
</p>
<p>Quantity:
<ui:inputNumber value="{!v.newitem.Quantity__c}"/>
</p>
</aura:component>
Error -
Challenge Not yet complete... here's what's wrong:
The campingList component isn't iterating the array of 'items' and creating 'campingListItem' components.
Please share the correct solution.
The component requires an attribute named items with the type of an array of camping item custom objects.
The component requires an attribute named newItem of type Camping_Item__c with default quantity and price values of 0.
The component displays the Name, Quantity, Price, and Packed form fields with the appropriate input component types and values from the newItem attribute.
The JavaScript controller checks to ensure that the Name, Quantity and Price values submitted are not null.
If the form is valid, the JavaScript controller pushes the newItem onto the array of existing items, triggers the notification that the items value provider has changed, and resets the newItem value provider with a blank sObjectType of Camping_Item__c.
My answer -
<aura:component >
<aura:attribute name="items" type="Camping_Item__c[]"/>
<aura:attribute name="newitem" type="Camping_Item__c[]" default="{ 'sobjectType': 'Camping_Item__c',
'Quantity__c'=0, 'Price__c'=0}"/>
<p>Name:
<ui:inputText value="{!v.newitem.name}"/>
</p>
<p>Packed:
<ui:inputCheckbox value="{!v.newitem.Packed__c}"/>
</p>
<p>Price:
<ui:inputCurrency value="{!v.newitem.Price__c}"/>
</p>
<p>Quantity:
<ui:inputNumber value="{!v.newitem.Quantity__c}"/>
</p>
</aura:component>
Error -
Challenge Not yet complete... here's what's wrong:
The campingList component isn't iterating the array of 'items' and creating 'campingListItem' components.
Please share the correct solution.
For this challenge there is much more to do. For this error you're giving, seems like you're not displaying the inputed items.
Hint : You know something like this :
If I give you more, it will be the solution and I am sure you want to find it yourself(more interesting)
Regards
Mouhamed
campingList Component code:
Controller code:
Do Mark this as best answer if you find it useful.
<aura:component >
<!-- <ol>
<li>Bug Spray</li>
<li>Bear Repellant</li>
<li>Goat Food</li>
</ol> -->
<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 aria-labelledby="newcampingform">
<!-- BOXED AREA -->
<fieldset class="slds-box slds-theme--default slds-container--small">
<legend id="newexpenseform" class="slds-text-heading--small slds-p-vertical--medium">
Camping
</legend>
<!-- CREATE NEW EXPENSE FORM -->
<form class="slds-form--stacked">
<div class="slds-form-element slds-is-required">
<div class="slds-form-element__control">
<ui:inputText aura:id="name" 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:inputText aura:id="price" label="Price"
class="slds-input"
labelClass="slds-form-element__label"
value="{!v.newItem.Price__c}"
placeholder="100$."/>
</div>
</div>
<div class="slds-form-element">
<div class="slds-form-element__control">
<ui:inputCheckbox aura:id="reimbursed" label="Packed?"
class="slds-checkbox"
labelClass="slds-form-element__label"
value="{!v.newItem.Packed__c}"/>
</div>
</div>
<div class="slds-form-element">
<ui:button label="Packed!"
class="slds-button slds-button--brand"
press="{!c.clickCreateItem}"/>
</div>
</form>
</fieldset>
<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>
</div>
</aura:component>
2) The campingListItem component code
<aura:component >
<aura:attribute name="item" type="Camping_Item__c" required="true" default=""/>
<p>
Name :<ui:outputText value="{!v.item.Name}"/>
Quantity :<ui:outputNumber value="{!v.item.Quantity__c}"/>
Price :<ui:outputCurrency value="{!v.item.Price__c}"/>
Packed:<ui:outputCheckbox value="{!v.item.Packed__c}"/>
</p>
</aura:component>
The controller will look like as follows:
({
clickCreateItem : function(component, event, helper) {
// Simplistic error checking
var validCamping = true;
// Name must not be blank
var nameField = component.find("name");
var name = nameField.get("v.value");
var quantityField = component.find("quantity");
var quantity = nameField.get("v.value");
var priceField = component.find("price");
var price = nameField.get("v.value");
if ($A.util.isEmpty(name)){
validCamping = false;
nameField.set("v.errors", [{message:"Camping name can't be blank."}]);
}
else {
nameField.set("v.errors", null);
}
if ($A.util.isEmpty(quantity)){
validCamping = false;
nameField.set("v.errors", [{message:"Camping quantity can't be blank."}]);
}
else {
nameField.set("v.errors", null);
}
if ($A.util.isEmpty(price)){
validCamping = false;
nameField.set("v.errors", [{message:"Camping price can't be blank."}]);
}
else {
nameField.set("v.errors", null);
}
if(validCamping){
var newItem = component.get("v.newItem");
console.log("Create item: " + JSON.stringify(newItem));
var newItems = component.get("v.items");
newItems.push(JSON.parse(JSON.stringify(newItem)));
component.set("v.items", newItems);
component.set("v.newItem",{ 'sobjectType': 'Camping_Item__c','Name': '','Quantity__c': 0,
'Price__c': 0,'Packed__c': false }/>);
}
}
})
I had the same issue and used Shobhit Saxena reponse to get a proper solution. Please use this to understand whyyour challenge was not working. There are three main files created/modified to get this to work:
campingList.cmp:
campingController.cmp: campingItem.cmp:
You can use controller helper. It's worked for me.
I am able to complete the form with the additional help from this post. But am still getting the error "The campingList controller isn't pushing a new item onto the array of items."
But if the array was empty, how would the form displays the data in the grid. Looks something wrong with the challenge evaluation. Has anyone got it passed in Trailhead?
Seems like you haven't used array attribute name as 'items' properly in your exercise.Trailhead verifies with mentioned names.
same error i was geting so i moved following block of code from "campingListHelper.js" to "campingListController.js" instead of calling helper function like this "helper.createItem(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") {
var campingArray = component.get("v.items");
campingArray.push(response.getReturnValue());
component.set("v.items", campingArray);
component.set("v.newItem",{ 'sobjectType':
'Camping_Item__c',
'Name': '',
'Quantity__c': 0,
'Price__c': 0,
'Packed__c': false });
}
});
$A.enqueueAction(action);
may be the variables names are different for your code. But the main thing is that "campingArray.push(response.getReturnValue());" should be in controller which is pushing newItems to existing items. let me know this works for u or not
Can you provide all the contents of your campingListController.js?
sure, here is the code for campingListController.js
This code worked for me. Actually challenge asks us to write logic in controller iteslef and not use helper at all (at least for this module).
1. CampingList.cmp
2. campingListController.js
3. campingListItem.cmp (Used in campingList.cmp)
4. campingHeader.cmp (Used in campingList.cmp)
This is the simplest code which would pass the challenge and will work as well. Hope this will all.
Thanks
I successfully used a helper, but had to move code from the helper to the controller for trailhead to accept my work.
<div class="slds-card slds-p-top--medium">
<header class="slds-card__header">
<h3 class="slds-text-heading--small">Camping 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>
({
clickCreateItem : function(component, event, helper) {
// Simplistic error checking
var validExpense = true;
// validate name is not null
var itemName = component.find("itemName").get("v.value");
if($A.util.isEmpty(itemName)){
validExpense = false;
component.find("itemName").set("v.errors", [{message: "Expense name field cannot be empty"}]) ;
}
else{
component.find("itemName").set("v.errors", null) ;
}
// validate price is not null
var itemPrice = component.find("itemPrice").get("v.value");
if($A.util.isEmpty(itemPrice)){
validExpense = false;
component.find("itemPrice").set("v.errors", [{message: "Expense price field cannot be empty"}]) ;
}
else{
component.find("itemPrice").set("v.errors", null) ;
}
// Validate quantity is not null
var itemQuantity = component.find("itemQuantity").get("v.value");
if($A.util.isEmpty(itemQuantity)){
validExpense = false;
component.find("itemQuantity").set("v.errors", [{message: "Expense Quantity field cannot be empty"}]) ;
}
else{
component.find("itemQuantity").set("v.errors", null) ;
}
// insert the expense record
if(validExpense){
var newItem = component.get("v.newItem");
console.log("createItem" + JSON.stringify(newItem));
// get the array variable
var theItems = component.get("v.items");
// Copy the expense to a new object
var newItem = JSON.parse(JSON.stringify(newItem));
// THIS IS A DISGUSTING, TEMPORARY HACK
// Push the item to array variable
theItems.push(newItem);
// set the array variable
component.set("v.items", theItems);
component.set("v.newItem",{ 'sobjectType': 'Camping_Item__c',
'Name': '',
'Quantity__c': 0,
'Price__c': 0,
'Packed__c': false });
}
}
})
This page has an error. You might just need to refresh it.
Assertion Failed!: Unknown controller action 'clickCreateItem' :
undefined Failing descriptor: {ui$button$controller$press}
Getting the above error while, creating new Camping Item. How to resolve it.
Akshay Deshmukh
saroj
All of you guys
@shubham_gupta... You are right. that was my issue as well. But it's not fair, as they did not mention that we have to use 'item' as the attribute name for completing the exercise. Only the functionalities should be tested, not the names of the attributes. (I understand it's tricky though)
Time for Trailhead to get smarter.. Let's wait for Einstein to jump in with the power of AI :D
My challenge isnt complete and heres whats wrong:
The campingList component doesn't appear to have a Quantity input field in the form using a Lightning Base component.
This is the form tag and its child components in my doccument. Can anyone correct. Thanks.
<form class="slds-form--stacked">
<div class="slds-form-element slds-is-required">
<div class="slds-form-element__control">
<lightning:input aura:id="campingName" label="Camping 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">
<lightning:input type="number" aura:id="quantity" label="Quantity"
class="slds-input"
value="{!v.newItem.Quantity__c}"
required="true"/>
</div>
</div>
<div class="slds-form-element">
<div class="slds-form-element__control">
<lightning:input type="number" aura:id="price" label="Price"
class="slds-input"
value="{!v.newItem.Price__c}" formatter="currency"/>
</div>
</div>
<div class="slds-form-element">
<lightning:input type="checkbox" aura:id="packed" label="Packed ?"
class="slds-checkbox"
value="{!v.newItem.Packed__c}"/>
</div>
<div class="slds-form-element">
<lightning:button label="Create Expense"
class="slds-button slds-button--brand"
onclick="{!c.createCampingList}"/>
</div>
</form>
<!-- CREATE NEW Camping ITEM FORM -->
<form class="slds-form--stacked">
<lightning:input aura:id="itemform" label="Name"
name="Name"
value="{!v.newItem.Name}"
required="true"/>
<lightning:input aura:id="itemform" label="Item"
name="campingitem"
value="{!v.newCamping.Item__c}"/>
<lightning:input type="number" aura:id="itemform" label="Quantity"
name="Quantity"
min="0"
formatter="number"
step="1"
value="{!v.newItem.Quantity__c}"
required="true"
messageWhenRangeUnderflow="Enter an amount that's at least 0"/>
<lightning:input type="number" aura:id="itemform" label="Price"
name="Price"
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="itemform" label="Packed?"
name="Packed"
checked="{!v.newItem.Packed__c}"/>
<lightning:button label="Packed!"
class="slds-m-top--medium"
variant="brand"
onclick="{!c.clickCreateItem}"/>
</form>
//Component code starts
<aura:component >
<aura:attribute name="item" type="Camping_Item__c" required="true"
default="{Name:'Tent', Price__c:100, Quantity__c:1, Packed__c:false}"/>
<P>Name: <ui:outputText value="{!v.item.Name}"/></P>
<p>
<lightning:input type="toggle"
label="Packed?"
name="packed"
checked="{!v.item.Packed__c}" />
</p>
<p>Price:
<lightning:formattedNumber value="{!v.item.Price__c}" style="currency"/>
</p>
<p>Quantity:
<lightning:formattedNumber value="{!v.item.Quantity__c}" style="currency"/>
</p>
</aura:component>
//Component code finish
Thanks.
I have this problem "The campingList JavaScript controller doesn't appear to be checking if form fields are valid."
I don't know what more I can validate to complete the challenge
This is my campingListContoller.js:
The challenge must had been updated, because in this moment I can't use "UI" components, I tried apply your validations in de Controller code and the error still appear.
Thanks.
I could finish the challenged with the help of another user, the code than I implement was
I recently completed the exercise. Please let us know if your form validation is now okay. The call back provided by Ender appears pretty okay.
Thanks.
The code provided by Ender works perfect for me.
Thank you for help!
For this challenge complete Follow This Code
if you complete challenge by this code so please like it
1.campingList.cmp
2.campingListItem.cmp
3.CampingHeader.cmp
campingListController.js
For Chacking Code Create A CampingApplication.app
Finally, 4 hours into a 35 minute question... and having lost half my hair as well as my confidence.... Your code worked perferfectly...
NOTE: I believe that the problem with the other answers is that Trailhead actually changed this module and left the old answers...
I have tried the code mentioned in your thread, but I am getting error message as follows:
Challenge Not yet complete... here's what's wrong:
The campingList component doesn't appear to have a Packed checkbox field in the form using a Lightning Base component.
While I am previewing Application, it is showing Packed component but not able to complete Trailhead challenge.
Regards
Chetan
You can get complete answer here.
http://faizanaz90.blogspot.com/2017/11/lightning-components-basics-input-data.html
Input Data Using Forms:--Lightning Components Basics
Follow the below Steps then you can clear your Challenge no#4
Step 1. CampingList.cmp
<aura:component >
<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>
<!-- CREATE NEW Campaing FORM -->
<form class="slds-form--stacked">
<!-- For Name Field -->
<lightning:input aura:id="expenseform" label="Camping Name"
name="expensename"
value="{!v.newItem.Name}"
required="true"/>
<!-- For Quantity Field -->
<lightning:input type="number" aura:id="campingform" label="Quantity"
name="expenseamount"
min="1"
value="{!v.newItem.Quantity__c}"
messageWhenRangeUnderflow="Enter minimum 1 Quantity"/>
<!-- For Price Field -->
<lightning:input aura:id="campingform" label="Price"
formatter="currency"
name="expenseclient"
value="{!v.newItem.Price__c}"
/>
<!-- For Check Box -->
<lightning:input type="checkbox" aura:id="campingform" label="Packed"
name="expreimbursed"
checked="{!v.newItem.Packed__c}"/>
<lightning:button label="Create Camping"
class="slds-m-top--medium"
variant="brand"
onclick="{!c.clickCreateItem}"/>
</form>
<!-- / CREATE NEW EXPENSE FORM -->
</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>
Controller:--
Step 2:- CampingListController.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){
var newCampingItem = component.get("v.newItem");
//helper.createCamping(component,newCampingItem);
var campings = component.get("v.items");
var item = JSON.parse(JSON.stringify(newCampingItem));
campings.push(item);
component.set("v.items",campings);
component.set("v.newItem",{ 'sobjectType': 'Camping_Item__c','Name': '','Quantity__c': 0,
'Price__c': 0,'Packed__c': false });
}
}
})
Step 3:- Create new lighting component
CampingListItem.cmp
<aura:component >
<aura:attribute name="item" type="Camping_Item__c"/>
<p>Name:
<ui:outputText value="{!v.item.Name}"/>
</p>
<p>Price:
<ui:outputCurrency value="{!v.item.Price__c}"/>
</p>
<p>Quantity:
<ui:outputNumber value="{!v.item.Quantity__c}"/>
</p>
<p>Packed:
<ui:outputCheckbox value="{!v.item.Packed__c}"/>
</p>
</aura:component>
Step 4:--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>
Check your challenge :)
Lightning Components Basics
Connect Components with Events
Step 2:- CampingListForm.cmp
**Step 5:- CampingListFormController.js**
**Step 6:-- CampingListItem.cmp**
**Step 7: CampingHeader.cmp **
**Step 8:--Apex Class:--campingListController.apxc**
**Step 9:- campingListHelper.js**
should be empty
**Step 10 :- campingListItemController.js **
**Step 11:-add event :- addItemEvent.evt **
you can complete your challenge.. Please don't forget to like if you clear your challenge.
:)
Did all steps + enabled domain in the process. I can see the component on the pagelayout.
ERROR:
There was an unhandled exception. Please reference ID: WXYSXYSZ. Error: Faraday::ClientError. Message: MALFORMED_QUERY: When retrieving results with Metadata or FullName fields, the query qualifications must specify no more than one row for retrieval. Result size: 2
And i have the follow code:
campingList.cmp campingListController.js what may be the failure?
Iff you are geting following error
Challenge Not yet complete... here's what's wrong:
The campingList component isn't iterating the array of 'items' and creating 'campingListItem' components.
but your funtionality is working fine according to you then check the attribute name in camping list item.It has to be "item" only otherwise it will say error in iteration.
Thanks @Shubham Gupta93 for highlighting the trailhead mistake/bug
clickCreateItem : function(component, event, helper) {
var validCampaign = component.find('campaignform').reduce(function (validSoFar, inputCmp) {
// Displays error messages for invalid fields
inputCmp.showHelpMessageIfInvalid();
return validSoFar && inputCmp.get('v.validity').valid;
}, true);
// If we pass error checking, do some real work
if(validCampaign){
// Create the new expense
var newItem = component.get("v.newItem");
console.log("Create expense: " + JSON.stringify(newItem));
var items = component.get("v.items");
items.push(newItem);
component.set("v.items", items);
component.set("v.newItem",{'sobjectType':'Camping_Item__c',
'Name':'',
'Price__c':0,
'Quantity':0,
'Packed__c': false});
}
}
})
Camping Header Component
-------------------------------------
<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 Component
------------------------------------
<aura:component >
<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 Camping FORM -->
<div class="slds-col slds-col--padded slds-p-top--large">
<c:campingHeader/>
<div aria-labelledby="newCampingForm">
<!-- BOXED AREA -->
<fieldset class="slds-box slds-theme--default slds-container--small">
<legend id="newCampingForm" class="slds-text-heading--small
slds-p-vertical--medium">
Add Expense
</legend>
<!-- CREATE NEW Camping FORM -->
<form class="slds-form--stacked">
<!-- For Name Field -->
<lightning:input aura:id="expenseform" label="Camping Name"
name="expensename"
value="{!v.newItem.Name}"
required="true"/>
<!-- For Quantity Field -->
<lightning:input type="number" aura:id="campingform" label="Quantity"
name="expenseamount"
min="1"
value="{!v.newItem.Quantity__c}"
messageWhenRangeUnderflow="Enter minimum 1 Quantity"/>
<!-- For Price Field -->
<lightning:input aura:id="campingform" label="Price"
formatter="currency"
name="expenseclient"
value="{!v.newItem.Price__c}"
/>
<!-- For Check Box -->
<lightning:input type="checkbox" aura:id="campingform" label="Packed"
name="expreimbursed"
checked="{!v.newItem.Packed__c}"/>
<lightning:button label="Create Camping"
class="slds-m-top--medium"
variant="brand"
onclick="{!c.clickCreateItem}"/>
</form>
<!-- / CREATE NEW EXPENSE FORM -->
</fieldset>
<!-- / BOXED AREA -->
</div>
<!-- / CREATE NEW EXPENSE -->
</div>
<!-- ITERATING ITEM LISTS -->
<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>
<!-- / ITERATIING ITEM LISTS -->
</aura:component>
===========================================================
CampingList Controller
----------------------------------
({
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){
var newCampingItem = component.get("v.newItem");
//helper.createCamping(component,newCampingItem);
var campings = component.get("v.items");
var item = JSON.parse(JSON.stringify(newCampingItem));
campings.push(item);
component.set("v.items",campings);
component.set("v.newItem",{ 'sobjectType': 'Camping_Item__c','Name': '','Quantity__c': 0,
'Price__c': 0,'Packed__c': false });
}
}
})
=========================================================
Camping List Item Component
-----------------------------
<aura:component >
<aura:attribute name="item" type="Camping_Item__c" required="true"/>
<p>Name:<ui:outputText value="{!v.item.Name}"/>
</p>
<p>Price:<ui:outputCurrency value="{!v.item.Price__c}" />
</p>
<p>Quantity:<ui:outputNumber value="{!v.item.Quantity__c}" />
</p>
<p>Packed:<ui:outputCheckbox value="{!v.item.Packed__c}"/>
</p>
<p>
<lightning:input type="toggle"
label="Packed?"
name="Packed"
checked="{!v.item.Packed__c}" />
</p>
<lightning:button label="Packed!"
onclick="{!c.packItem}"/>
</aura:component>
=======================================================================
This should do it for you! Hopefully you don't kill too much time on this like me lol.
Do not use <ui:input> in your code. Instead of this, use Lightning base component. Pasting the code that will pass the challenge:
<-------------------CampingApp-------------------->
<aura:application extends="force:slds">
<c:camping />
</aura:application>
<---------------------------------------------------------->
<-----------------CampingList Component---------------------------->
<aura:component >
<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'}"/>
<form class="slds-form--stacked">
<lightning:input aura:id= "cmpform" label="Name" name= "itemname" value="{!v.newItem.Name}"/>
<lightning:input aura:id= "cmpform" label="Quantity" name="itemquantity"
value="{!v.newItem.Quantity__c}" type="number" min= "1"/>
<lightning:input aura:id= "cmpform" label="Price" name="itemprice" value="{!v.newItem.Price__c}"
formatter="currency"/>
<lightning:input type="checkbox" aura:id="cmpform" label="Packed?"
checked="{!v.newItem.Packed__c}"/>
<lightning:button label="Submit" onclick="{!c.clickCreateItem}"/>
</form>
<aura:iteration items="{!v.items}" var="itm">
<c:campingListItem item="{!itm}"/><br/>
</aura:iteration>
</aura:component>
<------------------------------------------------------------------------------------------------->
<----------------------CampingList Controller---------------------------------------------->
({
clickCreateItem : function(component, event, helper) {
var validCamping = component.find("cmpform").reduce(
function(validSoFar, inputCmp){
inputCmp.showHelpMessageIfInvalid();
return validSoFar && inputCmp.get('v.validity').valid;
},true);
if(validCamping){
var newItem= component.get("v.newItem");
var items = component.get("v.items");
items.push(newItem);
component.set("v.items", items);
component.set("v.newItem", {'sObjectType' : 'Camping_Item__c', 'Name': '',
'Price__c' : '0', 'Quantity__c' : '0', 'Packed__c' : 'false'});
alert('New Item has been added!');
}
}
})
<-------------------------------------------------------------------------------------------------->
<----------------------CampingListItem component--------------------------------------->
<aura:component >
<aura:attribute name="item" type="Camping_Item__c" required = "True"/>
<p>Name: {!v.item.Name}</p>
<p>Price: <lightning:formattedNumber value="{!v.item.Price__c}"
style="currency"/></p>
<p>Quantity: <lightning:formattedNumber value="{!v.item.Quantity__c}" style="decimal"/></p>
<p><lightning:input type="checkbox"
aura:id="toggleswitch"
label="Packed"
name="packed"
checked="{!v.item.Packed__c}"/></p>
<lightning:button label="Packed!"
onclick="{!c.packItem}"/>
</aura:component>
<---------------------------------------------------------------------------------------------------->
<-----------------------------CampingListItem Controller---------------------------------->
({
packItem: function(component, event, helper) {
var a = component.get("v.item",true);
a.Packed__c = true;
component.set("v.item",a);
var btnClicked = event.getSource();
btnClicked.set("v.disabled",true);
}
})
<----------------------------------------------------------------------------------------------------->
Thanks and regards,
Rahul Sharma
I've practically tried several pieces of the code above including Rahul's since it's the most recent, I keep getting this error:
Challenge not yet complete... here's what's wrong:
The campingHeader component doesn't appear to be using 'lightning:layout'.
I created the following:
campingList.cmp
campingListItem.cmp
camping.cmp
campingController.js
campingHeader.cmp
campingListController.js
campingListItemController.js
I created all the above by following suggestions from various folks on this thread so I may have created a few extra components :)
Thanks in advance!
Ali
<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>
CAMPING APPLICATION TO PREVIEW :
----------------------------------
<aura:application extends="force:slds" >
<c:campingList />
</aura:application>
---------------------------
CAMPING HEADER COMPONENT:
---------------------------
<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>
---------------------------
CAMPING LIST COMPONENT:
---------------------------
<aura:component >
<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>
<!-- CREATE NEW Campaing FORM -->
<form class="slds-form--stacked">
<!-- For Name Field -->
<lightning:input aura:id="expenseform" label="Camping Name"
name="expensename"
value="{!v.newItem.Name}"
required="true"/>
<!-- For Quantity Field -->
<lightning:input type="number" aura:id="campingform" label="Quantity"
name="expenseamount"
min="1"
value="{!v.newItem.Quantity__c}"
messageWhenRangeUnderflow="Enter minimum 1 Quantity"/>
<!-- For Price Field -->
<lightning:input aura:id="campingform" label="Price"
formatter="currency"
name="expenseclient"
value="{!v.newItem.Price__c}"
/>
<!-- For Check Box -->
<lightning:input type="checkbox" aura:id="campingform" label="Packed"
name="expreimbursed"
checked="{!v.newItem.Packed__c}"/>
<lightning:button label="Create Camping"
class="slds-m-top--medium"
variant="brand"
onclick="{!c.clickCreateItem}"/>
</form>
<!-- / CREATE NEW EXPENSE FORM --></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>
------------------------------
CAMPING CONTROLLER :
------------------------------
({
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){
var newCampingItem = component.get("v.newItem");
//helper.createCamping(component,newCampingItem);
var campings = component.get("v.items");
var item = JSON.parse(JSON.stringify(newCampingItem));
campings.push(item);
component.set("v.items",campings);
component.set("v.newItem",{ 'sobjectType': 'Camping_Item__c','Name': '','Quantity__c': 0,
'Price__c': 0,'Packed__c': false });
}
}
})
---------------------------------------
CAMPING LIST ITEM COMPONENT:
---------------------------------------
<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>
Hello all! As of 12 March 2019, the <ui: ... > notation no longer clears the challenge.
This code isn't quite as pretty in terms of formatting as some of the code upthread, but this is what I used to pass the module.
CampingList.cmp:
campingListController.js:
This code will help you.
//campainList.cmp
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes" access="global" >
<aura:attribute name="items" type="Camping_Item__c[]" />
<aura:attribute name="newItem" type="Camping_Item__c" default="{'Price__c': 0, 'Packed__c': false, 'Quantity__c': 0, 'Name':'Test', 'sobjectType': 'Camping_Item__c'}" />
<lightning:layout>
<lightning:layoutItem padding="around-small" size="6">
<!-- CREATE NEW EXPENSE -->
<div aria-labelledby="newCampingItem">
<!-- BOXED AREA -->
<fieldset class="slds-box slds-theme--default slds-container--small">
<legend id="newCampingItem" class="slds-text-heading--small
slds-p-vertical--medium">
Add Camping Item
</legend>
<!-- CREATE NEW EXPENSE FORM -->
<form class="slds-form--stacked">
<lightning:input aura:id="campingItemForm" label="Name"
name="itemName"
value="{!v.newItem.Name}"
required="true"/>
<lightning:input type="number" aura:id="campingItemForm" label="Quantity"
name="itemQuantity"
min="1"
step="1"
value="{!v.newItem.Quantity__c}"
messageWhenRangeUnderflow="Enter the quantity atleast 1"/>
<lightning:input type="number" aura:id="campingItemForm" label="Price"
name="itemPrice"
min="0.1"
formatter="currency"
step="0.01"
value="{!v.newItem.Price__c}" />
<lightning:input type="checkbox" aura:id="campingItemForm" label="Packed ?"
name="itemPacked"
checked="{!v.newItem.Packed__c}"/>
<lightning:button label="Create Item"
class="slds-m-top--medium"
variant="brand"
onclick="{!c.clickCreateItem }"/>
</form>
<!-- / CREATE NEW EXPENSE FORM -->
</fieldset>
<!-- / BOXED AREA -->
</div>
<!-- / CREATE NEW EXPENSE -->
</lightning:layoutItem>
<lightning:layoutItem padding="around-small" size="6">
<aura:Iteration items="{!v.items}" var="item">
<c:campingListItem item="{!item}" />
</aura:Iteration>
</lightning:layoutItem>
</lightning:layout>
<!--
<ol>
<li>Bug Spray</li>
<li>Bear Repellant</li>
<li>Goat Food</li>
</ol>
-->
</aura:component>
//campaingListController.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){
var newCampingItem = component.get("v.newItem");
//helper.createCamping(component,newCampingItem);
var campings = component.get("v.items");
var item = JSON.parse(JSON.stringify(newCampingItem));
campings.push(item);
component.set("v.items",campings);
component.set("v.newItem",{ 'sobjectType': 'Camping_Item__c','Name': '','Quantity__c': 0,
'Price__c': 0,'Packed__c': false });
}
}
})
//compaingHeader.cmp
<aura:component >
<lightning:layout class="slds-page-header slds-page-header--object-home">
<lightning:layoutItem>
<lightning:icon iconName="action:goal" alternativeText="Camping List"/>
</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">Camping List</h2>
</div>
</lightning:layoutItem>
</lightning:layout>
</aura:component>
I hope you find the above solution helpful. If it does, please mark as Best Answer to help others too.
Thanks,
Ajay Dubedi
CampingList.cmp
campingListController.js
campingListItem.cmp
hope it helps !
IM getting this error in lightining experience-set up your org.....how to over come this error
https://techevangel.com/2018/04/15/trailhead-challenge-create-a-form-to-enter-new-items/
https://github.com/Mulodo-Salesforce-Training/trailhead-salesforce-challenge/blob/master/LightningComponentForm.md
Best Regards,
Akash Deep
Mohamed Arzad Ali thanks much..
it works finally..
CampingHeader.cmp
hi Mansi Gupta 13
I am Sharing Link. Please check
Please mark it as Best Answer so that it can help others in the future.
Thanks
Suraj Tripathi