function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Manoj Goswami 5Manoj Goswami 5 

I am stuck in Connect Components with Events Trailhead challange. please HELP !!!

I have trield almost every code and solution from forum still stuck into this challange.
Challange
Refactor Components and Communicate with Events
Refactor the input form for camping list items into its own component and communicate with component events.
Replace the HTML form in the campingList component with a new campingListForm component that calls the clickCreateItem JavaScript controller action when clicked.
The campingList component listens for a c:addItemEvent event and executes the action handleAddItem in the JavaScript controller. The handleAdditem method saves the record to the database and adds the record to the items value provider.
The addItemEvent event is of type component and has a Camping_Item__c type attribute named item.
The campingListForm registers an addItem event of type c:addItemEvent.
The campingListFormController JavaScript controller calls the helper's createItem method if the form is valid.
The campingListFormHelper JavaScript helper creates an addItem event with the item to be added and then fires the event. It then resets the newItem value provider with a blank sObjectType of type Camping_Item__c.

I am not pasting entire code as it is too lengthy.

I am trying from past 2 days, many hours ... still no luck.
Tried with every possible solution from Forum and StackExchange tried with fresh Trailhead Org, nothing worked.
with each try .. getting new errors.
Can someone please try the solution in their system and provide it in the comment ssection. That would be a great help.
Thanks in advance,
Manoj
 
Best Answer chosen by Manoj Goswami 5
bhanu_prakashbhanu_prakash
HI
Mark as best answer, If it resloves !!
(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>

please follow same instruction again in New trailhead playground you can able to acheive it.
Mark as resloved if it helps :) :)
Thanks, 
Bhanu Prakash
visit ForceLearn.com

All Answers

bhanu_prakashbhanu_prakash
HI
Mark as best answer, If it resloves !!
(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>

please follow same instruction again in New trailhead playground you can able to acheive it.
Mark as resloved if it helps :) :)
Thanks, 
Bhanu Prakash
visit ForceLearn.com
This was selected as the best answer
Manoj Goswami 5Manoj Goswami 5
Hi @banu_prakash,
Can you help me with this one also -- > https://developer.salesforce.com/forums/ForumsMain?id=9060G0000005cWBQAY
Thanks in advance.
Silvio Altmann DeveloperSilvio Altmann Developer
@bhanu_prakash your code does not work and produces errors. Not good coding practice. Solving the challenge with copy&paste is one thing, writing functioning code is the other..... 
stan_sfdcstan_sfdc
The answer no longer works. It gives the error - 

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.
 
Vikram Sisodia 8Vikram Sisodia 8
Hi,
Solution provided by bhanu_prakash is correct. You just need to make few changes in  campingList Component & CampingListForm. You can copy all the design elements proposed by bhanu. And use below elements for campingList Component & campingListForm.   I hope it would fix the issue which you have reported.
1. campingList Component
<aura:component controller="CampingListController" implements="force:appHostable,flexipage:availableForAllPageTypes" access="global" >
    <aura:attribute name="items" type="Camping_Item__c[]" />
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    <aura:handler name="addItem" event="c:addItemEvent"  action="{!c.handleAddItem }"/>
    
   <div aria-labelledby="newitemform">
     <fieldset class="slds-box slds-theme--default slds-container--small">
       <c:campingListForm />
     </fieldset>
   </div>
<lightning:layout>
    	<lightning:layoutItem padding="around-small" size="3">
            <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>
2.CampingListForm
<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 -->
     <lightning:layout>
        <lightning:layoutItem padding="around-small" size="4">
            <!-- 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:layout>
   <!-- / CREATE NEW ITEM FORM -->
</aura:component>



 
Madhumitha M 3Madhumitha M 3
hi ,
@bhanu_prakash
please help me to resolve this 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.