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
Derek Bennett 5Derek Bennett 5 

Stuck in trailhead - Lightning Components Basics-Connect Components with Events

I am stuc on this challenge and its very frustrating. 

For some reason I cannot save the component code, i get an error message when trying to save:

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


Here is the code im trying to save. anyone know why it wont allow me to save it?

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

</aura:component>
Best Answer chosen by Derek Bennett 5
sfdcMonkey.comsfdcMonkey.com
hi Derek Bennett
you got this error because maybe you can't create addItemEvent lightning event (see 7 number part in below code)
and
use below 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>
let me inform if it helps you and if you have any issue with it you can ask here :) thanks


 



 

All Answers

Jayanth ThathapudiJayanth Thathapudi
Hi
Please find the solution in below link
https://developer.salesforce.com/forums/?id=906F0000000kDmtIAE

Regards
Jay
sfdcMonkey.comsfdcMonkey.com
hi Derek Bennett
you got this error because maybe you can't create addItemEvent lightning event (see 7 number part in below code)
and
use below 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>
let me inform if it helps you and if you have any issue with it you can ask here :) thanks


 



 
This was selected as the best answer
Derek Bennett 5Derek Bennett 5
Thank You piyush_soni!!

The issue was because I was not adding "addItemEvent lightning event"

appreciate the help
dandamudidandamudi
 hi @plyush_soni  in your answer  6th part i found a error in line 3, u have to use component.getEvent instead of component.getItem("addItem");

createItem : function(component,newItem) {
         
        var addEvent = component.getEvent("addItem");
        addEvent.setParams({"item" : newItem});
        addEvent.fire();
    },
Atla Satheesh 8Atla Satheesh 8
Hi Piyush,

I am getting below mentioned error.i used the code which you have posted.

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.

coudl you please help me.


 
bheemudu neelibheemudu neeli
Hi Piyush..
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.

 
Rishabh Agrawal 18Rishabh Agrawal 18
Hi,

Replace your campingListForm component with below code and it will work--
 
<aura:component >
    
     <aura:attribute name="newItem" type="Camping_Item__c"
     default="{ 'sobjectType': 'Camping_Item__c',
                    'Name': '',
                    'Packed__c': false,
                    'Price__c': '0',
                    'Quantity__c': '0' }"/>
	<aura:registerEvent name="addItem" type="c:addItemEvent"/>
    
  <div aria-labelledby="newitemform">
      <fieldset class="slds-box slds-theme--default slds-container--small">
    
        <legend id="newitemform" class="slds-text-heading--small 
          slds-p-vertical--medium">
          Add Camping Item
        </legend>
    
        <form class="slds-form--stacked">
    
          <lightning:input type="text"
                         label="Camping Item Name"
                         name="Name"
                         value="{!v.newItem.Name}"
                         required="true"/> 
        <lightning:input type="number" aura:id="campinglistitemform" label="Quantity"
                             name="itemquantity"
                             min="1"
                             step="1"
                             value="{!v.newItem.Quantity__c}"
                             placeholder="0"/>
        <lightning:input type="number" aura:id="newItemForm" 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" 
                         label="Packed?"  
                         name="Packed"
                         checked="{!v.newItem.Packed__c}"/>
        <lightning:button variant="brand"
                         label="Create Camping Item" 
                         class="slds-m-top--medium"
                         onclick="{!c.clickCreateItem}"/>    
                
        </form>
    
      </fieldset>
</div>

</aura:component>
and on campingListForm controller replace submitForm to clickCreateItem. 

Let me know if anything else came up.
Regards,
Rishabh
Vinothini murugesh 10Vinothini murugesh 10
Hi All,

Please find below code and it is wrking perfectly:

1) Campaingnlistctroller.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 itemToSave=event.getParam("item");
      
        var action=component.get("c.saveItem");
        action.setParams({"item":itemToSave});
        
        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);
}
    
})


2)campaignlistcmp:
<aura:component controller="CampingListController">
    <aura:attribute name="items" type="Camping_Item__c[]" />
    
    <aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
    <aura:handler name="addItem" event="c:addItemEvent" action="{!c.handleAddItem}"/>
    
        
    <lightning:layout >
        <lightning:layoutItem padding="around-small" size="6">
            <c:campingListForm/>
        </lightning:layoutItem>
    </lightning:layout>
    
    <lightning:card title="Camping Items">
        <p class="slds-p-horizontal--small">
            <aura:iteration items="{!v.items}" var="item">
                <c:campingListItem item="{!item}" />
            </aura:iteration>
        </p>
    </lightning:card>
</aura:component>

campaignlisthelper:
({
    createItem : function(component,event,item) {
        console.log('step6');
        var action=component.get("c.saveItem");
        action.setParams({
            "item": item
        });
        action.setCallback(this,function(response){
            var state=response.getState();
            if(state=="SUCCESS"){
                console.log('step7');
                var items=component.get("v.items");
                items.push(response.getReturnValue());
                component.set("v.items",items);
            }
            else{
                console.log('State Returned '+state);
            }
        });
        $A.enqueueAction(action);
    }
})

3)Campaignlistformcmp:
<aura:component >
    <aura:attribute name="newItem" type="Camping_Item__c" default= "{'sobjectType':'Camping_Item__c',
                                                                    'Name':'',
                                                                    'Packed__c':false,
                                                                    'Quantity__c':0,
                                                                    'Price__c':0
                                                                    }"/>
    <aura:registerEvent name="addItem" type="c:addItemEvent"/>
    
    <form>
        <lightning:input aura:id="itemform" label="Camping Name" value="{!v.newItem.Name}" messageWhenValueMissing="Camping Name cannot be blank" required="true"/>
        <lightning:input aura:id="itemform" type="number" label="Quantity" min="1" value="{!v.newItem.Quantity__c}" messageWhenRangeUnderflow="Enter minimum 1 Quantity" required="true" />
        <lightning:input aura:id="itemform" type="itemform" label="Price" formatter="currency" value="{!v.newItem.Price__c}" min="0.1" step="0.01" messageWhenRangeUnderflow="Enter an amount that's at least $0.10."  required="true"/>
        <lightning:input aura:id="itemform" type="checkbox" label="Packed?" checked="{!v.newItem.Packed__c}" />
        <lightning:input type="date" label="Date"/>
        <lightning:button label="Create Camping" class="slds-m-top--medium"
                              variant="brand"
                              onclick="{!c.clickCreateItem}"/>
    </form>
</aura:component>


4)Campaingnlistfomrcontroller:js
({
    clickCreateItem: function(component, event, helper) {
        console.log('step1');
        var validItem = component.find('itemform').reduce(function (validSoFar, inputCmp) {

            // Displays error messages for invalid fields

           inputCmp.showHelpMessageIfInvalid();
           return validSoFar && inputCmp.get('v.validity').valid;

        }, true);


        if(validItem){
            console.log('step2');
            var item = component.get("v.newItem");
            var newItem = JSON.parse(JSON.stringify(item));
            console.log('step3');
            //var items=component.get("v.items");
            console.log('step4');
            //items.push(newItem);
            //component.set("v.items", items);
            
           
         helper.createItem(component,event,newItem);
             
        }
    }
})

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

6)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;
 }
}

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

8)CampaignListitemcmp:
<aura:component >
    <aura:attribute name="item" type="Camping_Item__c" required="true" />
    
   <p>Name:
       <ui:outputText value="{!v.item.Name}"/>
    </p>
    
    <p>Price:
        <lightning:formattedNumber value="{!v.item.Price__c}" style="currency"/>
    </p>
    <p>Quantity:
        <lightning:formattedNumber value="{!v.item.Quantity__c}"/>
    </p>
    
    <p>
        <lightning:input type="toggle" label="Packed" checked="{!v.item.Packed__c}" />
    </p>
    
    <lightning:button label="Packed!" onclick="{!c.packItem}"/>
</aura:component>


9)CampaignListitemcontroller.js:
({
    packItem : function(component, event, helper) {
        component.set("v.item.packed__c",true);
        var btn=event.getSource();
         btn.set("v.disabled",true);
    }
})
Lokesh G 14Lokesh G 14

This worked for me, Thanks Murugesh :)