+ Start a Discussion
Tavva Sai KrishnaTavva Sai Krishna 

Connect to Salesforce with Server-Side Controllers - Lightning Component Basics.

Hi All , getting the error while completing this module. While my application is running correctly.

Error: Challenge Not yet complete... here's what's wrong: The campingList JavaScript helper isn't saving the new record to the database or adding it to the 'items' value provider.

I am copying code for the finding the bug.

Apex Class:
public class CampingListController {
	@auraenabled
    public static List<Camping_Item__c> getItems (){
        List<Camping_Item__c> CI = [select id, name,price__c,Quantity__c,Packed__c from Camping_Item__c ];
        return CI;
    }
    @auraenabled
    public static Camping_Item__c saveItem (Camping_Item__c CampingItem){
        insert campingItem;
        return campingItem;
    }
}
CampingList.cmp
<aura:component controller="CampingListController">
    <aura:handler name = "init" value="{!this}" action = "{!c.doInit}"/>
	<aura:attribute name="items" type="Camping_Item__c[]"/>
    <aura:attribute name="er" type="boolean" default="false"/>
    <aura:attribute name="newItem" type="Camping_Item__c"    default="{ 'sobjectType': 'Camping_Item__c',
                         'Name': '',
                         'Price__c': 0,
                         'Quantity__c': 0,                         
                         'Packed__c': false
                       }"/>
    <ui:inputText value="{!v.newItem.Name}" aura:id="name" label="name"/>
    <ui:inputCheckbox value="{!v.newItem.Packed__c}" aura:id="Packed" label="Packed"/>
    <ui:inputCurrency value="{!v.newItem.Price__c}"  aura:id="Price" label="Price"/>
    <ui:inputNumber value="{!v.newItem.Quantity__c}" aura:id="Quantity" label="Quantity"/>
    <ui:button label="Create Expense" press="{!c.CreateCamping}" aura:id="button"/>
    <br/>
	<aura:iteration items="{!v.items}" var="PerItem">
        
        <c:campingListItem item="{!PerItem}" />
    </aura:iteration>
</aura:component>
CampingList.js
({
	
    doInit  : function(component, event, helper) {
		var action = component.get("c.getItems");
        action.setCallback(this, function(response){
            var state = response.getState();
           
            if (component.isValid() && state === "SUCCESS") {
           
               
                component.set("v.items", response.getReturnValue());
                 
            }
        });
        
        $A.enqueueAction(action);
	},
    
    CreateCamping : function(component, event, helper){
        
        helper.validateFields (component,component.find("name"));
        helper.validateFields (component,component.find("Price"));
        helper.validateFields (component,component.find("Quantity"));
        if(component.get("v.er") === false)
        {
            var lstItems = component.get("v.items");
            var Item = component.get("v.newItem");
            console.log('Before:'+lstItems);
            lstItems.push(Item);
            helper.CreateCampaign(component,Item);
            component.set("v.items",lstItems);  
             console.log('After:'+lstItems);
            component.set("v.newItem",{ 'sobjectType': 'Camping_Item__c',
                'Name': '',
                'Quantity__c': 0,
                'Price__c': 0,
                'Packed__c': false });
           
        }
	}
    
    
})

CampingListHelper.js
({
	
    validateFields : function (component,field) {
        
        var nameField = field;
        console.log('yes:'+nameField);
        var expname = nameField.get("v.value"); 
        if ($A.util.isEmpty(expname)){
           component.set("v.er",true);
           nameField.set("v.errors", [{message:"this field can't be blank."}]);
        }
        else {
            nameField.set("v.errors", null);
        }
    },
    
    CreateCampaign : function (component,Item){         
        var action = component.get("c.saveItem");
        action.setParams({"CampingItem":Item});
        action.setCallback(this,function(response){
            var state = response.getState();
            if (component.isValid() && state === "SUCCESS") {
                console.log('save');
            }
        });
       $A.enqueueAction(action);        
    }
})
campingListItem.cmp
 
<aura:component >
    
   
    <aura:attribute type="Camping_Item__c" name="item" required="true"/>
    Name:
    <ui:outputText value="{!v.item.Name}" /><br/>
    Packed:
    <ui:outputCheckbox value="{!v.item.Packed__c}" /><br/>
    Price:
    <ui:outputCurrency value="{!v.item.Price__c}" /><br/>
   
    Quantity:
     <ui:outputNumber value="{!v.item.Quantity__c}" /><br/>
    
    <ui:button label="Packed!"  press="{!c.packItem}" aura:id = "Button"/> <br/>
</aura:component>

campingListItem.js
({
	    
    packItem : function(component, event, helper) {
		var pack = component.get("v.item");
        pack.Packed__c = true;
        component.set("v.item",pack);
        var btnClicked = event.getSource();
        btnClicked.set("v.disabled",true);
        
	}
    
    
})


Help me out with it.

Thanks and Regards,
Sai Krishna Tavva.


 
Best Answer chosen by Tavva Sai Krishna
Tavva Sai KrishnaTavva Sai Krishna
Hi Fernandez & Jeff,
 Thanks for your quick response. However the error is not with the js variable name . I have shifted the some code from CampingList.js to CampinListHelper.js . Now i completed the challenge. See the below updated code.

CampingList.js
({
	
    doInit  : function(component, event, helper) {
		var action = component.get("c.getItems");
        action.setCallback(this, function(response){
            var state = response.getState();
           
            if (component.isValid() && state === "SUCCESS") {
           
               
                component.set("v.items", response.getReturnValue());
                 
            }
        });
        
        $A.enqueueAction(action);
	},
    
    CreateCamping : function(component, event, helper){
        
        helper.validateFields (component,component.find("name"));
        helper.validateFields (component,component.find("Price"));
        helper.validateFields (component,component.find("Quantity"));
        if(component.get("v.er") === false)
        {     
            //Here I removed the lines and shifted the code to the helperJs       
            console.log('Before:'+Items);            
            helper.CreateCampaign(component,Item);             
             console.log('After:'+Items);                    
        }
	}    
})
CampingListHelper.js
 
({
	
    validateFields : function (component,field) {
        
        var nameField = field;
        console.log('yes:'+nameField);
        var expname = nameField.get("v.value"); 
        if ($A.util.isEmpty(expname)){
           component.set("v.er",true);
           nameField.set("v.errors", [{message:"this field can't be blank."}]);
        }
        else {
            nameField.set("v.errors", null);
        }
    },
    
    CreateCampaign : function (component,Item){ 
		    
        var action = component.get("c.saveItem");
        action.setParams({"CampingItem":Item});
        action.setCallback(this,function(response){
            var state = response.getState();
            if (component.isValid() && state === "SUCCESS") {
                console.log('save');
            }
        });
        $A.enqueueAction(action);  
//Below lines are shifted from controller Js to helperJs
        var Items = component.get("v.items"); 
        var Item = component.get("v.newItem"); 
        Items.push(Item);    
        component.set("v.items",Items); 
        component.set("v.newItem",{ 'sobjectType': 'Camping_Item__c',
                'Name': '',
                'Quantity__c': 0,
                'Price__c': 0,
                'Packed__c': false });
    }
})

Thanks and Regards,
Sai Krishna Tavva.

 

All Answers

Jeff DouglasJeff Douglas
It looks like you are doing things correctly. Email me (jdouglas@salesforce.com) and I'll help you out.

Jeff Douglas
Trailhead Developer Advocate
Guiomar Fernández de BobadillaGuiomar Fernández de Bobadilla
Hi,

Try changing 'lstItems' for 'items' in lines #26, #29 and #31 in CampingList.js

It worked for me! Let me know if it helps you!

Regards.
Tavva Sai KrishnaTavva Sai Krishna
Hi Fernandez & Jeff,
 Thanks for your quick response. However the error is not with the js variable name . I have shifted the some code from CampingList.js to CampinListHelper.js . Now i completed the challenge. See the below updated code.

CampingList.js
({
	
    doInit  : function(component, event, helper) {
		var action = component.get("c.getItems");
        action.setCallback(this, function(response){
            var state = response.getState();
           
            if (component.isValid() && state === "SUCCESS") {
           
               
                component.set("v.items", response.getReturnValue());
                 
            }
        });
        
        $A.enqueueAction(action);
	},
    
    CreateCamping : function(component, event, helper){
        
        helper.validateFields (component,component.find("name"));
        helper.validateFields (component,component.find("Price"));
        helper.validateFields (component,component.find("Quantity"));
        if(component.get("v.er") === false)
        {     
            //Here I removed the lines and shifted the code to the helperJs       
            console.log('Before:'+Items);            
            helper.CreateCampaign(component,Item);             
             console.log('After:'+Items);                    
        }
	}    
})
CampingListHelper.js
 
({
	
    validateFields : function (component,field) {
        
        var nameField = field;
        console.log('yes:'+nameField);
        var expname = nameField.get("v.value"); 
        if ($A.util.isEmpty(expname)){
           component.set("v.er",true);
           nameField.set("v.errors", [{message:"this field can't be blank."}]);
        }
        else {
            nameField.set("v.errors", null);
        }
    },
    
    CreateCampaign : function (component,Item){ 
		    
        var action = component.get("c.saveItem");
        action.setParams({"CampingItem":Item});
        action.setCallback(this,function(response){
            var state = response.getState();
            if (component.isValid() && state === "SUCCESS") {
                console.log('save');
            }
        });
        $A.enqueueAction(action);  
//Below lines are shifted from controller Js to helperJs
        var Items = component.get("v.items"); 
        var Item = component.get("v.newItem"); 
        Items.push(Item);    
        component.set("v.items",Items); 
        component.set("v.newItem",{ 'sobjectType': 'Camping_Item__c',
                'Name': '',
                'Quantity__c': 0,
                'Price__c': 0,
                'Packed__c': false });
    }
})

Thanks and Regards,
Sai Krishna Tavva.

 
This was selected as the best answer
Sreeharsha KaranamSreeharsha Karanam
I am getting error message while saving CampingList.cmp stating no controller found <Name_prefix>.CampingListController not found. help me on this.
 
Tavva Sai KrishnaTavva Sai Krishna
Hi Sreeharsha,

You can follow this link for your reference.
https://developer.salesforce.com/forums/ForumsMain?id=906F0000000kDPpIAM

Regards,
Sai Krishna Tavva.
 
Jeff DouglasJeff Douglas
We just updated this module with some new code. Please try the challenge check again. Sorry for the inconvenience. 

​Jeff Douglas
Trailhead Developer Advocate
Richard Clarke - Artisan ConsultingRichard Clarke - Artisan Consulting
I am getting "The campingList JavaScript controller isn't setting the 'item' as a parameter or saving the record correctly." even though the code is working and updating Salesforce as it should when a camping item is created
Richard Clarke - Artisan ConsultingRichard Clarke - Artisan Consulting
FYI in my campingListController.js I had to comment the call to "helper.createItem(component, item)" and move all that code into the controller then the challenge passed.  I did not change any code, just moved it from the helper to the controller.
Caleb KuesterCaleb Kuester
It seems as though there was some confusion between "Camping" and "Campaign" on this one. I know that this issue has long-since been resolved, but I would be sure to correct the naming issue before continuing. In coding, small issues like these can create hours of work. 

Secondly, the helper did not appear to change anything. It received the information, but did nothing with it. That was all completed in the non-helper .js file. That could explain the error message: 

"Error: Challenge Not yet complete... here's what's wrong: The campingList JavaScript helper isn't saving the new record to the database or adding it to the 'items' value provider."
Orchay NaehOrchay Naeh
i was still encountering problems even after i checked the answers here
had a problem with the set params function for the action - i was using different name for the signature where calling the apex controller.
another problem was that updating view method block should have be placed in the helper and used only when the component is valid and and the response status is "SUCCESS"

====================================================================
camping.cmp:

<aura:component >
    <c:campingHeader />
    <c:campingList />
</aura:component>

=================================================================
campingHeader.cmp

<aura:component >
    <lightning:layout class="slds-page-header slds-page-header--object-home">
        <lightning:layoutItem >
            <lightning:icon iconName="action:goal" size="large" alternativeText="My Camping List"/>
        </lightning:layoutItem>
        <lightning:layoutItem padding="horizontal-small">
            <div class="page-section page-header" role="banner">
                <p class="slds-text-heading--label">Campings</p>
                <h1 class="slds-text-heading--label">Camping List</h1>
            </div>
        </lightning:layoutItem>
    </lightning:layout>
</aura:component>

==========================================================================
campingList.cmp

<aura:component controller="CampingListController">
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <aura:attribute name="items" type="Camping_Item__c[]"/>
    <aura:attribute name="er" type="boolean" default="false"/>
    <aura:attribute name="newItem" type="Camping_Item__c"    default="{ 'sobjectType': 'Camping_Item__c',
                         'Name': '',
                         'Price__c': 0,
                         'Quantity__c': 0,                         
                         'Packed__c': false
                       }"/>
    
    <ui:inputText value="{!v.newItem.Name}" aura:id="name" label="name"/>
    <ui:inputCheckbox value="{!v.newItem.Packed__c}" aura:id="Packed" label="Packed"/>
    <ui:inputCurrency value="{!v.newItem.Price__c}"  aura:id="Price" label="Price"/>
    <ui:inputNumber value="{!v.newItem.Quantity__c}" aura:id="Quantity" label="Quantity"/>
    <ui:button label="CreateItem" press="{!c.CreateCamping}" aura:id="button"/>
    <br/>
    <aura:iteration items="{!v.items}" var="PerItem">
        <c:campingListItem item="{!PerItem}"/>
    </aura:iteration>
</aura:component>

======================================================================
campingListController.js = campingList.js*controller

({
    doInit  : function(component, event, helper) {
        var action = component.get("c.getItems"); // c of apex controller where getitems takes no arguments
        action.setCallback(this, function(response){
            var state = response.getState();
           
            if (component.isValid() && state === "SUCCESS") {
               // setting the items array at the view page- campingList.cmp
         component.set("v.items", response.getReturnValue()); 
            }
            else {
            console.log("Failed with state: " + state);
        }

        });
        
        $A.enqueueAction(action);
    },
    
    CreateCamping : function(component, event, helper){
        
    //sending fields for validations at the helper function: campingList*Helper.js
        helper.validateFields (component,component.find("name"));
        helper.validateFields (component,component.find("Price"));
        helper.validateFields (component,component.find("Quantity"));

        // if any of the firled s failes validation the v.er is being set to true
    
    if(component.get("v.er") === false)
        {
            // get object and object list
            var lstItems = component.get("v.items");
            var Item = component.get("v.newItem");
            
            // call to helper function to communicate with the apex controller
            helper.createItem(component,Item);

        }
    }    
})

================================================================

campingListHelper.js = campingList.js*helper

({
    
    validateFields : function (component,field) {
        
        var nameField = field;
        console.log('yes:'+nameField);
        var expname = nameField.get("v.value"); 
        if ($A.util.isEmpty(expname)){
           component.set("v.er",true);
           nameField.set("v.errors", [{message:"this field can't be blank."}]);
        }
        else {
            nameField.set("v.errors", null);
        }
    },
    
    createItem: function(component, item) {
            console.log("from helper "+item);
            // attempt to 
            
            // var newItem = item;//component.get("v.newItem");
            // console.log("from helper overrriden Item"+newItem);
        
        var action = component.get("c.saveItem"); // function at the apex controller
            console.log("action "+action);
            action.setParams({"campingItem": newItem}); // the function takes a prameter "campingItem" we insert "newItem" into it
            action.setCallback(this, function(response){
            var state = response.getState();
        if (component.isValid() && state === "SUCCESS") {
        var lstItems = component.get("v.items");
            var Item = component.get("v.newItem");
            
            // call to helper function to communicate with the apex controller
            
            //UPDATE VIEWER PART ONLY IF THE UPSERT WAS SECCESSFULL


            lstItems.push(Item);
            component.set("v.items",lstItems);  

            
            // trigger update reset newItem fields
            component.set("v.newItem",{ 'sobjectType': 'Camping_Item__c',
                'Name': '',
                'Quantity__c': 0,
                'Price__c': 0,
                'Packed__c': false });                }
                else
                {
                    console.log("something failed "+state);
                }
            });
            $A.enqueueAction(action);
    }
})

===============================================================

campingListItem.cmp

<aura:component >

    <aura:attribute type="Camping_Item__c" name="item" required="true"/>
    Name:
      <lightning:formattedText value="{!v.item.Name}" /><br/>
    Packed:
    <lightning:input type="toggle" checked="{!v.item.Packed__c}" /><br/>
    Price:
    <lightning:formattedNumber value="{!v.item.Price__c}" style="currency"/><br/>
   
    Quantity:
     <lightning:formattedNumber value="{!v.item.Quantity__c}" /><br/>
    
    <ui:button label="Packed!"  press="{!c.packItem}" aura:id="Button"/> <br/>
</aura:component>

========================================================================

harnessApp.app

<aura:application extends="force:slds">
       
        <!-- This component is the real "app" -->
        <c:camping />

</aura:application>

=======================================================================

campingListController.apxc

public with sharing class CampingListController {

    @AuraEnabled
    public static List<Camping_Item__c> getItems() {
        // Perform isAccessible() checking first, then
        return [SELECT Id, Name, price__c, Quantity__c, Packed__c 
                FROM Camping_Item__c];
    }
    
    @AuraEnabled
    public static Camping_Item__c saveItem(Camping_Item__c campingItem) {
       // List<Camping_Item__c> newList = getItems();
       // system.debug('the new item '+campingItem);
       // system.debug('campingItem b4 adding'+newList);
       //newList.add(campingItem);
       // system.debug('campingItem after adding'+newList);
        upsert campingItem; 
        return campingItem;
    }
}
venkat raj 9venkat raj 9
TrailHead Exercise -  Lightning Component Basics - Connect to Salesforce with Server-Side Controllers
Below code will help in completing the Connect to Salesforce with Server-Side Controllers exercise

CampingList Component

<aura:component controller="CampingListController" >

    <aura:attribute name="items" type="Camping_Item__c[]" />
   
    <aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
   
    <aura:attribute name="newItem" type="Camping_Item__c" default="{'sObjectType':'Camping_Item__c','Quantity__c':0,'Price__c':0}" />
      
    <br/><br/>
    <p>Name:
    <ui:inputText aura:id="name" value="{!v.newItem.Name}" Label="Name" />
    </p><br/>
    <p>Quantity:
    <ui:inputNumber aura:id="quantity" value="{!v.newItem.Quantity__c}" Label="Quantity" />
    </p><br/>
    <p>Price:
    <ui:inputCurrency aura:id="price" value="{!v.newItem.Price__c}" Label="Price" />
    </p><br/>
    <p>Packed?:
    <ui:inputCheckBox value="{!v.newItem.Packed__c}" Label="Packed" />
    </p><br />
   
    <ui:button label="Submit" press="{!c.PushItems}" />
   
    <aura:iteration items="{!v.items}" var="item">
   
    <p> <ui:outputText value="{!item.Name}" /> </p>
   
    <p> <ui:outputNumber value="{!item.Quantity__c}" /> </p>
   
    <p> <ui:outputCurrency value="{!item.Price__c}" />  </p>
   
    <p> <ui:outputCheckbox value="{!item.Packed__c}" /> </p>  
       
    </aura:iteration>
       

</aura:component>


CampingList Controller


({

    doInit : function(component,event,helper){
       
       var action = component.get("c.getItems");
       
        action.setCallback(this,function(response){
           
           var state = response.getState();
           
            if(component.isValid() && state === "SUCCESS"){
               
                console.log('From action variable : '+JSON.parse(JSON.stringify(response.getReturnValue())));
               
               
                component.set("v.items",JSON.parse(JSON.stringify(response.getReturnValue())));
               
            }
            else{
               
                console.log("Failed with State : " + state);
            }
           
        });
       
       
        $A.enqueueAction(action);
       
    },
   
   
   
    PushItems : function(component, event, helper) {
       
        var validItem = true;

       
        var nitem = component.get("v.newItem");
       
        var iName = component.find("name");
        var iQuantity = component.find("quantity");
        var iPrice = component.find("price");
       
        if($A.util.isEmpty(iName.get("v.value"))){
         console.log('Checking Name is null');   
            validItem = false;
            iName.set("v.errors",[{message:"Item Name cannot be blank"}]);
           
           
        }else if($A.util.isEmpty(iQuantity.get("v.value"))){
           
            validItem = false;
            iQuantity.set("v.errors",[{message:"Item Quantity cannot be blank"}]);
           
        }else if($A.util.isEmpty(iPrice.get("v.value"))){           
           
            validItem = false;
            iPrice.set("v.errors",[{message:"Item Price cannot be blank"}]);
           
        }
       
        if(validItem){
           
            var pitem = JSON.parse(JSON.stringify(nitem));
           
helper.createItem(component,pitem);
           
           
        }
       
       
}

})



CampingList Helper

({
createItem : function(component,strcamp) {

       
        var action = component.get("c.saveItem");
       
        action.setParams({
           
            "strcamp" : strcamp
           
        });
       
        action.setCallback(this,function(response){
           
            var state = response.getState();
           
            console.log('Status of the response is : ' + state);
           
            if(state === "SUCCESS"){
           
                var ilist = component.get("v.items");
               
                ilist.push(strcamp);
               
                component.set("v.items",ilist);
                                      
                component.set("v.newItem",{'sObjectType':'Camping_Item__c','Name':' ','Quantity__c':0,'Price__c':0});
                   
            }
            else{
               
                console.log('Errored Out');
               
            }
           
        });
       
        $A.enqueueAction(action);
       
       
}

})



CampingListController APEX Class


public class CampingListController{

@AuraEnabled
public static list<Camping_Item__c> getItems(){

    System.debug('Method is invoked');

    return ([select Name,Packed__c,Price__c,Quantity__c from Camping_Item__c]);

}


@AuraEnabled
public static void saveItem(Camping_Item__c strcamp){

    //Camping_Item__c ci     = (Camping_Item__c)JSON.deserialize(strcamp,Camping_Item__c.class);
   
    //System.debug('Inserted Camping Item  : ' + ci);
   
    insert strcamp;

}



}
 
Christoph Hallmann 4Christoph Hallmann 4

I have also an issue with this.

My code works but cannot pass trailhead

 

campingListHelper.js

 

```

({
    createItem : function(item, action, component) {
        var items = component.get("v.items");
        
        action.setParams({
            "item" : item
        });

        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                
                items.push(item);
                component.set("v.items", items);
                component.set("v.newItem",{ 'sobjectType':
                                           'Camping_Item__c',
                                           'Name': '',
                                           'Quantity__c': 0,
                                           'Price__c': 0,
                                           'Packed__c': false });
            }
        });
            
        $A.enqueueAction(action);

    }
})

```

campingListController.js

 

```

({
    clickCreateItem : function(component, event, helper) {
        var validListItem = component.find('itemform').reduce(function(validSoFar, inputCmp){
            inputCmp.showHelpMessageIfInvalid();
            return validSoFar && inputCmp.get('v.validity').valid;
        }, true);    
        
        if (validListItem) {
            var currentItem = component.get("v.newItem");
            var newItem = JSON.parse(JSON.stringify(currentItem));
            var action = component.get("c.saveItem");  
            helper.createItem(newItem, action, component);
           
        }
    },
    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) {
            console.log("callback");
            var state = response.getState();
            if (state === "SUCCESS") {
                component.set("v.items", response.getReturnValue());
            }
            else {
                console.log("Failed with state: " + state);
            }
        });
        // Send action off to be executed
        $A.enqueueAction(action);
    }
})

```

 

CampingListController.apxc

```

public class CampingListController {    
    
    @AuraEnabled
    public static List<Camping_Item__c> getItems() {
        System.debug('Called get Items');
        List<Camping_Item__c> campingItems = [SELECT Name, Price__c, Quantity__c, Packed__c FROM Camping_Item__c];
        return campingItems;
    }
    
    @AuraEnabled
    public static Camping_Item__c saveItem(Camping_Item__c item) {
        try{
            upsert item;
            System.debug('success');
        } catch (Exception e) {
           System.debug('error found'); 
        }
        
        return item;
        
    }
}

```

 

my error message is

```` 

Challenge not yet complete... here's what's wrong:
The campingList JavaScript helper doesn't appear to have the correct functionality. Ensure that it is saving the new record to the database and in the callback, pushing the new record to the array of existing items (e.g., v.items) and setting the modified array of items to the 'items' value provider to display the updated list.

 

```


thanks for any help!