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
MattEvansMattEvans 

Perfectly working and correctly factored solution but get error: "The campingList component doesn't have a Quantity field using an inputNumber UI component"

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!
 
Best Answer chosen by MattEvans
James LoghryJames Loghry
I noticed your fields are prefixed with a namespace.  As with all other trailhead modules, it's assumed you're working from a clean, non-namespaced developer org.  Sometimes the namespace interferes with the module verification process and you can run into goofy errors like this.  The first thing a member of the trailhead team will ask is if you started from a clean developer org.  If not, then usually the solution is to spin up a new org and "try again".

That being said, it could be something very nitpicky with the order of attributes in your element. I would try investigating this first.  For instance, I copied my component from the code in the module and it worked well enough.  Try replacing the Quantity form element (starting with the div class="slds-form-elment") with the following to see if it helps (or at least produces a different error):
 
<div class="slds-form-element">
    <div class="slds-form-element__control slds-is-required">
        <ui:inputNumber aura:id="quantity" label="Quantity"
            class="slds-input"
            labelClass="slds-form-element__label"
            value="{!v.newItem.c4tch__Quantity__c}"/>
    </div>
</div>

If that doesn't work, then you're probably looking at spinning up that new developer org and trying the challenge again, unfortunately.

All Answers

MattEvansMattEvans
... I forgot to include this in the question: campingListFormController.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); 
        }
    }
})

 
James LoghryJames Loghry
I noticed your fields are prefixed with a namespace.  As with all other trailhead modules, it's assumed you're working from a clean, non-namespaced developer org.  Sometimes the namespace interferes with the module verification process and you can run into goofy errors like this.  The first thing a member of the trailhead team will ask is if you started from a clean developer org.  If not, then usually the solution is to spin up a new org and "try again".

That being said, it could be something very nitpicky with the order of attributes in your element. I would try investigating this first.  For instance, I copied my component from the code in the module and it worked well enough.  Try replacing the Quantity form element (starting with the div class="slds-form-elment") with the following to see if it helps (or at least produces a different error):
 
<div class="slds-form-element">
    <div class="slds-form-element__control slds-is-required">
        <ui:inputNumber aura:id="quantity" label="Quantity"
            class="slds-input"
            labelClass="slds-form-element__label"
            value="{!v.newItem.c4tch__Quantity__c}"/>
    </div>
</div>

If that doesn't work, then you're probably looking at spinning up that new developer org and trying the challenge again, unfortunately.
This was selected as the best answer
MattEvansMattEvans
Hi all,
Just wanted to let you know, that while Namespacing is best practice (especially if you're looking at going ISV) it messes Trailhead's challenge caluclator. I had to move this solution to a non-namespaced org and "bing!!" it worked !
James LoghryJames Loghry
Matt,

That's what I stated in my response to your problem.  I'm just curious why my response wasn't marked as the best answer.

Thanks,
- James
MattEvansMattEvans
Hi James, when I went back to the topic I didn't see your Answer, so I wrote up the solution for others to see. Happy to mark yours as Best Answer! I'll see if it will show this time...
Alexandru JugravuAlexandru Jugravu
I had the same problem and I found a much faster solution:
I simply replaced "v.newItem.c4tch__Quantity__c" with "v.newItem.Quantity__c", only in the component.
It complained again about the <namespace>__Packed__c  (Price__c was fine though), and I applied the same solution.

This tricked the Trailhead verification.
The challenge was then complete - however, the list will not show the correct values  for Quantity and Packed :D.