TransWikia.com

The campingList JavaScript controller isn't calling 'saveItem'

Salesforce Asked by oobarbazanoo on December 11, 2020

The Trailhead challenge check is telling me the following:

Challenge Not yet complete… here’s what’s wrong:
The campingList JavaScript controller isn’t calling ‘saveItem’ in the Apex class to save the record or setting the ‘item’ as a parameter for the ‘saveItem’ action.

The app is really not working as expected, but I can not guess why is that.

Here is my code.

campingApp.app :

<aura:application extends="force:slds">
    <c:camping />
</aura:application>

camping.cmp :

<aura:component controller="CampingListController">
    <aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
    <aura:attribute name="items" type="Camping_Item__c[]" default="[]"/>
    <aura:attribute name="item" type="Camping_Item__c" default="{ 
                        'sobjectType': 'Camping_Item__c',
                        'campingItemName': 'campingItemNameDefault',
                        'Price__c': 0,
                        'Quantity__c': '0',
                        'Packed__c': false }"/>
    <c:campingHeader />
    <!-- <c:campingItemForm item="{!v.item}" items="{!v.items}" /> -->
    <c:campingList items="{!v.items}"/>
</aura:component>

CampingListController.apxc :

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

    @AuraEnabled
    public static Camping_Item__c saveItem(Camping_Item__c item) {
        upsert item;
        return item;
    }
}

campingController.js :

({
    logArray : function(component, event, helper) {
        var items = component.get("v.items");
        console.log(JSON.stringify(items));
    },
    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);
    }
})

campingHeader.cmp :

<aura:component >
<lightning:layout class="slds-page-header slds-page-header--object-home">
        <lightning:layoutItem >
            <lightning:icon iconName="action:goal"/>
        </lightning:layoutItem>
        <lightning:layoutItem padding="horizontal-small">
            <div class="page-section page-header">
                <h1 class="slds-text-heading--label">Camping list</h1>
            </div>
        </lightning:layoutItem>
    </lightning:layout>

</aura:component>

campingList.cmp :

<aura:component controller="CampingListController">
    <aura:attribute name="items" type="Camping_Item__c[]" />
    <aura:handler name="addItemEvent" event="c:addItemEvent"
        action="{!c.handleAddItem}"/>
    <c:campingListForm/>
    <aura:iteration items="{!v.items}" var="item">
        <c:campingListItem item="{!item}" />
    </aura:iteration>

</aura:component>

campingListController.js :

({
    clickCreateItem : function(component, event, helper) {
        var isValidItem = component.find('campingItemForm').reduce(function(total,currentValue, index,arr)
                                                           {
                                                               currentValue.showHelpMessageIfInvalid();
                                                               return total && currentValue.get('v.validity').valid;
                                                           }, true);
        if(isValidItem) {
            helper.createItem(component);
        }
    },
    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 item = event.getParam("item");
        helper.updateExpense(component, item);
    }
})

campingListHelper.js :

({
    createItem : function(component, item) {
        var action = component.get("c.saveItem");

            //var newItem = component.get("v.newItem");
            action.setParams({
                "item": item
            });

            action.setCallback(this, function(response){
                var state = response.getState();
                if (state === "SUCCESS") {
                    var items = component.get("v.items");
                    items.push(response.getReturnValue());
                    item = {sobjectType: "Camping_Item__c"};;
                    component.set("v.newItem", item);
                    component.set("v.items", items);
                }
            });

            $A.enqueueAction(action);
    }
})

campingListForm.cmp :

<aura:component controller="CampingListController">
    <aura:attribute name="newItem" type="Camping_Item__c" default="{ 
                        'sobjectType': 'Camping_Item__c',
                        'campingItemName': 'SSSSSSSSSSSSSSSSS',
                        'Price__c': 0,
                        'Quantity__c': '0',
                        'Packed__c': false }"/>
    <aura:registerEvent name="addItem" type="c:addItemEvent"/>
    <form class="slds-form--stacked">      
            <lightning:input aura:id="campingItemForm" label="Name"
                             name="Name"
                             value="{!v.newItem.Name}"/>
            <lightning:input type="number" aura:id="campingItemForm" label="Quantity"
                             name="Quantity"
                             min="1"
                             step="1"
                             value="{!v.newItem.Quantity__c}"
                             placeholder="0"/>
            <lightning:input type="number" aura:id="campingItemForm" label="Price"
                             name="Price"
                             formatter="currency"
                             value="{!v.newItem.Price__c}"/>
            <lightning:input aura:id="campingItemForm" type="checkbox" label="Packed"  
                             name="campingItemIsPacked"
                             checked="{!v.newItem.Packed__c}"/>
            <lightning:button label="Create Camping Item" 
                              class="slds-m-top--medium"
                              variant="brand"
                              onclick="{!c.clickCreateItem}"/>
        </form>
</aura:component>

campingListFormController.js :

({
    clickCreateItem : function(component, event, helper) {
        var isValidItem = component.find('campingItemForm').reduce(function(total,currentValue, index,arr)
                                                           {
                                                               currentValue.showHelpMessageIfInvalid();
                                                               return total && currentValue.get('v.validity').valid;
                                                           }, true);
        if(isValidItem) {
            helper.createItem(component);
        }
    }
})

campingListHelper.js :

({
    createItem : function(component) {
        var action = component.get("c.saveItem");

            var newItem = component.get("v.newItem");
            action.setParams({
                "item": newItem
            });

            action.setCallback(this, function(response){
                var state = response.getState();
                if (state === "SUCCESS") {
                    /* var items = component.get("v.items");
                    items.push(response.getReturnValue());
                    newItem = {sobjectType: "Camping_Item__c"};
                    component.set("v.newItem", newItem);
                    component.set("v.items", items); */

                    var addItemEvent = component.getEvent("addItem");
                    addItemEvent.setParams({"item": response.getReturnValue()});
                    addItemEvent.fire();
                    newItem = {sobjectType: "Camping_Item__c"};
                    component.set("v.newItem", newItem);
                }
            });

            $A.enqueueAction(action);
    }
})

addItemEvent.evt :

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

As you can tell from the line :

<aura:component controller="CampingListController">

in the campingList.cmp the .apxc controller is attached to the campingList.cmp.

Next, as you can tell from the line :

helper.updateExpense(component, item);

in the campingListController.js and then from the line :

var action = component.get("c.saveItem");

in the campingListHelper.js the .apxc function saveItem is called.

So, what is still needs to be checked is that the event arrives to the handler in campingList.cmp.

Here is the event which will be thrown from the campingListForm.cmp :

<aura:registerEvent name="addItem" type="c:addItemEvent"/>

and in the campingListFormHelper.js it is actually thrown :

addItemEvent.fire();

Hence I am expecting the even to get caught in the campingList.cmp over here:

<aura:handler name="addItemEvent" event="c:addItemEvent"
        action="{!c.handleAddItem}"/>

and as a result call the saveItem function.

But the Trailhead continues to tell me that that call does not happen. And after debugging I see that it really does not. What am I doing wrong here?

2 Answers

You need to register the handler with the same name as when you register the event.

You have

<aura:registerEvent name="addItem" type="c:addItemEvent"/>
<aura:handler name="addItemEvent" event="c:addItemEvent"
        action="{!c.handleAddItem}"/>

You need

<aura:registerEvent name="addItem" type="c:addItemEvent"/>
<aura:handler name="addItem" event="c:addItemEvent"
        action="{!c.handleAddItem}"/>

For more information, take a look at the docs for handling component events.

This is assuming of course that you have confirmed that your event is actually firing.

Correct answer by Kyle on December 11, 2020

in campingListController.js, you have updateExpense in:

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

I assume "expense" is not correct? Probably from copy and paste from expense example.

Answered by Doug on December 11, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP