• MattEvans
  • NEWBIE
  • 15 Points
  • Member since 2012
  • Architect
  • Salesforce :)

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 1
    Questions
  • 7
    Replies
Driving me crazy. Please help! I have a perfectly working sollution, correctly factored according to the challenge. I've compared against other solutions on the message boards and I don't see where the miss is. It matches all the criteria the challenge asks for but I get the very obtuse error message:
"The campingList component doesn't have a Quantity field using an inputNumber UI component" - which is clearly an incorrect statement as the UI components are supposed to be on the campaignListForm component.

Here is my code (not posting the apex controller, camping.cmp, campingHeader.cmp or campingListItem as they haven't changed in this challenge and are all working ok):
(Note: I do have a namespace on my org, perhaps that is the issue? Custom field names are xxx__MyField__c, but this hasn't been a problem before)

addItemEvent.cmp
<aura:event type="COMPONENT">
    <aura:attribute name="item" type="Camping_Item__c"/>
</aura:event>
campinglist.cmp  
<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[]"/>

    <!-- stripped some of the sdls styling here to reduce the post length -->
    <h3 class="slds-text-heading--small">Items</h3>
        <table ...>
                <aura:iteration items="{!v.items}" var="item">
                    <tr>
                        <c:campingListItem item="{!item}"/>
                    </tr>
        <...table>   
    <c:campingListForm />
</aura:component>

campingListForm.cmp
<aura:component >
	<aura:attribute name="newItem" type="Camping_Item__c"
                default="{ 'sobjectType': 'Camping_Item__c',
                'Name': '',
                'c4tch__Price__c': 0,
                'c4tch__Quantity__c': 0,
                'c4tch__Packed__c': false }"/>
    <aura:registerEvent name="addItem" type="c:addItemEvent"/>
	<!-- stripped some of the sdls styling here to reduce the post length -->
		<form class="slds-form--stacked"> 
	        <div class="slds-form-element slds-is-required">
	            <div class="slds-form-element__control">
	                <ui:inputText aura:id="itemName" value="{!v.newItem.Name}" label="Name" class="slds-input" labelClass="slds-form-element__label"  required="true"/>
	            </div>
	        </div>
	        <div class="slds-form-element slds-is-required">
	            <div class="slds-form-element__control">
	                <ui:inputNumber aura:id="itemQuantity" value="{!v.newItem.c4tch__Quantity__c}" label="Quantity" class="slds-input" labelClass="slds-form-element__label" required="true" />
	            </div>
	        </div>
	        <div class="slds-form-element slds-is-required">
	            <div class="slds-form-element__control">
	                <ui:inputCurrency aura:id="itemPrice" value="{!v.newItem.c4tch__Price__c}" label="Price" class="slds-input" labelClass="slds-form-element__label" required="true" />
	            </div>
	        </div>
	        <div class="slds-form-element slds-is-required">
	            <div class="slds-form-element__control">
	                <ui:inputCheckbox aura:id="itemPacked" value="{!v.newItem.c4tch__Packed__c}" label="Packed" class="slds-input" labelClass="slds-form-element__label" />
	            </div>
	        </div>
	        <div class="slds-form-element">
	            <ui:button label="Create Camping Item" class="slds-button slds-button--brand" press="{!c.submitForm}"/>
	        </div>
	    </form>
	</div>
</aura:component>

camingListFormController.js
({
	// handle the click, validate and request creation, clean off the form
    submitForm: function(component, event, helper) {
        if (helper.validateItem(component)) {
            var newItem = component.get("v.newItem");
            helper.createItem(component,newItem); 
        }
    }
})

campingListController.js
({
    doInit : function(component, event, helper) {
        var action = component.get("c.getItems");
        action.setCallback(this, function(response) {
                console.log(this+':'+response);
                var state = response.getState();
                if (component.isValid() && state === "SUCCESS") {
                    component.set("v.items", response.getReturnValue());
                } else {
                    console.log("Failed with state: " + state);
                }
            });
        $A.enqueueAction(action);
    },
    
    handleAddItem : function(component,event,helper) {
        var newItem = event.getParam("item");
        // Note, to do this correctly it should be in a helper: helper.addItem(component,newItem); but the challenge requests the functionality to be in the handleAddItem method
        // Submit the item
        var action = component.get("c.saveItem");
        action.setParams({
            "newItem": newItem
        });
        action.setCallback(this, function(response){
            var state = response.getState();
            if (component.isValid() && state === "SUCCESS") {
                // done, add the new item to the list
                var items = component.get("v.items");
                items.push(response.getReturnValue());
                component.set("v.items", items);
                // coud kill a spinner here if we had one
            } else {
                console.log("Failed with state: " + state);
            }
        });
        // could create a spinner here if we had one
        $A.enqueueAction(action); 
    }
})

campingListHelper.js ** see note in previous class, this is not called, though it is the correct way to decompose the problem **
({
	addItem : function(component, newItem) {
        // Submit the item
        var action = component.get("c.saveItem");
        action.setParams({
            "newItem": newItem
        });
        action.setCallback(this, function(response){
            var state = response.getState();
            if (component.isValid() && state === "SUCCESS") {
                // done, add the new item to the list
                var items = component.get("v.items");
                items.push(response.getReturnValue());
                component.set("v.items", items);
                // coud kill a spinner here if we had one
            } else {
                console.log("Failed with state: " + state);
            }
        });

        // coud create a spinner here if we had one
        $A.enqueueAction(action);
    }
});

campingListFormHelper.js
({
	validateItem : function (component) {
		var validItem = true;
        // Get fields
        var itemName = component.find("itemName");
        var itemPrice = component.find("itemPrice");
        var itemQuantity = component.find("itemQuantity");
        var itemPacked = component.find("itemPacked");
        // Validate
        if ($A.util.isEmpty(itemName.get("v.value"))){
            validItem = false;
            itemName.set("v.errors", [{message:"Required field"}]);
        }
        else {
            itemName.set("v.errors", null);
        }
        if ($A.util.isEmpty(itemPrice.get("v.value"))){
            validItem = false;
            itemPrice.set("v.errors", [{message:"Required field"}]);
        }
        else {
            itemPrice.set("v.errors", null);
        }
        if ($A.util.isEmpty(itemQuantity.get("v.value"))){
            validItem = false;
            itemQuantity.set("v.errors", [{message:"Required field"}]);
        }
        else {
            itemQuantity.set("v.errors", null);
        }
        return validItem;
	},

	createItem : function(component, newItem) {
		// Fire the add item event
        console.log('Raising event for newItem:'+newItem);
        var addItem = component.getEvent("addItem"); // the name we have given to fire event of type "addItemEvent" as defined by the challenge
        addItem.setParams({ "item": newItem });
        addItem.fire();

        //Clear form
        component.set("v.newItem",
                      {'sobjectType' : 'c4tch__Camping_Item__c',
                       'Name' : '',
                       'c4tch__Quantity__c' : 0,
                       'c4tch__Price__c' : 0,
                       'c4tch__Packed__c' : false});
	}
})
Help!
 
Driving me crazy. Please help! I have a perfectly working sollution, correctly factored according to the challenge. I've compared against other solutions on the message boards and I don't see where the miss is. It matches all the criteria the challenge asks for but I get the very obtuse error message:
"The campingList component doesn't have a Quantity field using an inputNumber UI component" - which is clearly an incorrect statement as the UI components are supposed to be on the campaignListForm component.

Here is my code (not posting the apex controller, camping.cmp, campingHeader.cmp or campingListItem as they haven't changed in this challenge and are all working ok):
(Note: I do have a namespace on my org, perhaps that is the issue? Custom field names are xxx__MyField__c, but this hasn't been a problem before)

addItemEvent.cmp
<aura:event type="COMPONENT">
    <aura:attribute name="item" type="Camping_Item__c"/>
</aura:event>
campinglist.cmp  
<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[]"/>

    <!-- stripped some of the sdls styling here to reduce the post length -->
    <h3 class="slds-text-heading--small">Items</h3>
        <table ...>
                <aura:iteration items="{!v.items}" var="item">
                    <tr>
                        <c:campingListItem item="{!item}"/>
                    </tr>
        <...table>   
    <c:campingListForm />
</aura:component>

campingListForm.cmp
<aura:component >
	<aura:attribute name="newItem" type="Camping_Item__c"
                default="{ 'sobjectType': 'Camping_Item__c',
                'Name': '',
                'c4tch__Price__c': 0,
                'c4tch__Quantity__c': 0,
                'c4tch__Packed__c': false }"/>
    <aura:registerEvent name="addItem" type="c:addItemEvent"/>
	<!-- stripped some of the sdls styling here to reduce the post length -->
		<form class="slds-form--stacked"> 
	        <div class="slds-form-element slds-is-required">
	            <div class="slds-form-element__control">
	                <ui:inputText aura:id="itemName" value="{!v.newItem.Name}" label="Name" class="slds-input" labelClass="slds-form-element__label"  required="true"/>
	            </div>
	        </div>
	        <div class="slds-form-element slds-is-required">
	            <div class="slds-form-element__control">
	                <ui:inputNumber aura:id="itemQuantity" value="{!v.newItem.c4tch__Quantity__c}" label="Quantity" class="slds-input" labelClass="slds-form-element__label" required="true" />
	            </div>
	        </div>
	        <div class="slds-form-element slds-is-required">
	            <div class="slds-form-element__control">
	                <ui:inputCurrency aura:id="itemPrice" value="{!v.newItem.c4tch__Price__c}" label="Price" class="slds-input" labelClass="slds-form-element__label" required="true" />
	            </div>
	        </div>
	        <div class="slds-form-element slds-is-required">
	            <div class="slds-form-element__control">
	                <ui:inputCheckbox aura:id="itemPacked" value="{!v.newItem.c4tch__Packed__c}" label="Packed" class="slds-input" labelClass="slds-form-element__label" />
	            </div>
	        </div>
	        <div class="slds-form-element">
	            <ui:button label="Create Camping Item" class="slds-button slds-button--brand" press="{!c.submitForm}"/>
	        </div>
	    </form>
	</div>
</aura:component>

camingListFormController.js
({
	// handle the click, validate and request creation, clean off the form
    submitForm: function(component, event, helper) {
        if (helper.validateItem(component)) {
            var newItem = component.get("v.newItem");
            helper.createItem(component,newItem); 
        }
    }
})

campingListController.js
({
    doInit : function(component, event, helper) {
        var action = component.get("c.getItems");
        action.setCallback(this, function(response) {
                console.log(this+':'+response);
                var state = response.getState();
                if (component.isValid() && state === "SUCCESS") {
                    component.set("v.items", response.getReturnValue());
                } else {
                    console.log("Failed with state: " + state);
                }
            });
        $A.enqueueAction(action);
    },
    
    handleAddItem : function(component,event,helper) {
        var newItem = event.getParam("item");
        // Note, to do this correctly it should be in a helper: helper.addItem(component,newItem); but the challenge requests the functionality to be in the handleAddItem method
        // Submit the item
        var action = component.get("c.saveItem");
        action.setParams({
            "newItem": newItem
        });
        action.setCallback(this, function(response){
            var state = response.getState();
            if (component.isValid() && state === "SUCCESS") {
                // done, add the new item to the list
                var items = component.get("v.items");
                items.push(response.getReturnValue());
                component.set("v.items", items);
                // coud kill a spinner here if we had one
            } else {
                console.log("Failed with state: " + state);
            }
        });
        // could create a spinner here if we had one
        $A.enqueueAction(action); 
    }
})

campingListHelper.js ** see note in previous class, this is not called, though it is the correct way to decompose the problem **
({
	addItem : function(component, newItem) {
        // Submit the item
        var action = component.get("c.saveItem");
        action.setParams({
            "newItem": newItem
        });
        action.setCallback(this, function(response){
            var state = response.getState();
            if (component.isValid() && state === "SUCCESS") {
                // done, add the new item to the list
                var items = component.get("v.items");
                items.push(response.getReturnValue());
                component.set("v.items", items);
                // coud kill a spinner here if we had one
            } else {
                console.log("Failed with state: " + state);
            }
        });

        // coud create a spinner here if we had one
        $A.enqueueAction(action);
    }
});

campingListFormHelper.js
({
	validateItem : function (component) {
		var validItem = true;
        // Get fields
        var itemName = component.find("itemName");
        var itemPrice = component.find("itemPrice");
        var itemQuantity = component.find("itemQuantity");
        var itemPacked = component.find("itemPacked");
        // Validate
        if ($A.util.isEmpty(itemName.get("v.value"))){
            validItem = false;
            itemName.set("v.errors", [{message:"Required field"}]);
        }
        else {
            itemName.set("v.errors", null);
        }
        if ($A.util.isEmpty(itemPrice.get("v.value"))){
            validItem = false;
            itemPrice.set("v.errors", [{message:"Required field"}]);
        }
        else {
            itemPrice.set("v.errors", null);
        }
        if ($A.util.isEmpty(itemQuantity.get("v.value"))){
            validItem = false;
            itemQuantity.set("v.errors", [{message:"Required field"}]);
        }
        else {
            itemQuantity.set("v.errors", null);
        }
        return validItem;
	},

	createItem : function(component, newItem) {
		// Fire the add item event
        console.log('Raising event for newItem:'+newItem);
        var addItem = component.getEvent("addItem"); // the name we have given to fire event of type "addItemEvent" as defined by the challenge
        addItem.setParams({ "item": newItem });
        addItem.fire();

        //Clear form
        component.set("v.newItem",
                      {'sobjectType' : 'c4tch__Camping_Item__c',
                       'Name' : '',
                       'c4tch__Quantity__c' : 0,
                       'c4tch__Price__c' : 0,
                       'c4tch__Packed__c' : false});
	}
})
Help!
 
Hi everyone!
I have a problem with the challenge, my App work fine but I don´t pass the challenge. This is my code:

campingList.cmp:
 
<aura:component controller="CampingListController">
    
    <ltng:require styles="/resource/SLDS105/assets/styles/salesforce-lightning-design-system-ltng.css"/>

	<aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
    
     <aura:attribute name="newItem" type="Camping_Item__c"
     default="{ 'sobjectType': 'Camping_Item__c',
                    'Price__c': 0,
                    'Quantity__c': 0}"/>
    
    <div class="slds-card slds-p-top--medium">
    <ui:inputText aura:id="campname" label="Camping Name"
        value="{!v.newItem.Name}" required="true"/>
    <ui:inputCheckbox aura:id="packed" label="Packed?"
        value="{!v.newItem.Packed__c}"/>
     <ui:inputCurrency aura:id="price" label="Price"
        value="{!v.newItem.Price__c}" required="true"/>
     <ui:inputNumber aura:id="quantity" label="Quantity"
        value="{!v.newItem.Quantity__c}" required="true"/>
    
    <ui:button label="Create Camping" press="{!c.clickCreateCamping}"/>
    </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">Campings</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>

campingListController.js:
 
({
    
    // Load expenses 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);
	},
    
    clickCreateCamping: function(component, event, helper) {
        
        if(helper.validateCampingForm(component)){
	        // Create the new expense
	        var newCamping = component.get("v.newItem");
	        helper.createItem(component, newCamping);
	    }
    }
})
campingListHelper.js
 
({
    
    createItem: function(component, camping) {
        
        var action = component.get("c.saveItem");
        action.setParams({
            "item": camping
        });
    	action.setCallback(this, function(response){
        var state = response.getState();
        if (component.isValid() && state === "SUCCESS") {
            var campings = component.get("v.items");
            campings.push(response.getReturnValue());
            component.set("v.items", campings);
        }
    	});
    	$A.enqueueAction(action);
    },
    
    validateCampingForm: function(component) {
      
     	var validQuantity = true;
        var validPrice = true;

        var nameField = component.find("campname");
        var campname = nameField.get("v.value");
        
        var quantityField = component.find("quantity");
        var quantity = quantityField.get("v.value");
        
        var priceField = component.find("price");
        var price = priceField.get("v.value");
        
        if ($A.util.isEmpty(campname) || $A.util.isEmpty(quantity) || $A.util.isEmpty(price)){
            validQuantity = false;
            validPrice = false;
            nameField.set("v.errors", [{message:"Camping name, quantity or price can't be blank."}]);
        }
        else {
            nameField.set("v.errors", null);
        }
		
		return(validQuantity && validPrice);        
	}
})
CampingListController.apxc:
 
public with sharing class CampingListController {

    @AuraEnabled
    public static List<Camping_Item__c> getItems() {
    
        // Check to make sure all fields are accessible to this user
        String[] fieldsToCheck = new String[] {
            'Id', 'Name', 'Packed__c', 'Price__c', 'Quantity__c'
        };
        
        Map<String,Schema.SObjectField> fieldDescribeTokens = 
            Schema.SObjectType.Camping_Item__c.fields.getMap();
        
        for(String field : fieldsToCheck) {
            if( ! fieldDescribeTokens.get(field).getDescribe().isAccessible()) {
                throw new System.NoAccessException();
                return null;
            }
        }        
        
        // Perform isAccessible() checking first, then
        return [SELECT Id, Name, Packed__c, Price__c, Quantity__c 
                FROM Camping_Item__c];
    }
    
    @AuraEnabled
    public static Camping_Item__c saveItem(Camping_Item__c item) {
        // Perform isUpdatable() checking first, then
        upsert item;
        return item;
    }
}
I am still getting this 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.


My App save the new record into the database and add it to the "items" list.
Thanks for your answers!




 
I'm trying to complete the Connect Components with Events trailhead and am getting this message when checking the challenge:

Challenge Not yet complete... here's what's wrong: 
The campingList component doesn't have a Name field using an inputText UI component.

This does not make sense to me as this challenge moved the input form to a new bundle. Why does it seem to want a inputText UI component in the campingList component?

I am using an inputText UI control in the form component and including the component on the CampingList component.

I feel I'm missing a step.  Ideas?

Thanks.

I'm designing some flows for which I'd like the finishLocation behavior to change depending on the path of the flow.  Depending what happens in the flow, I need users to end up at different pages when the flow is over.  Is there a way to do that without writing custom code?

  • February 13, 2012
  • Like
  • 0