[SalesForce] Child component not showing property of attribute passed from parent

I am trying to complete a Trailhead challenge (Input Data Using Form) and according to it if I pass an attribute from the parent to the child I should be able to access it and view all the properties. Here is what I am doing from the parent component –

<aura:component access="global">
<aura:attribute access="global" name="items" type="Camping_Item__c[]"></aura:attribute>
<aura:attribute name="newItem" type="Camping_Item__c" 
                default="{ 'sobjectType':'Camping_Item__c','Quantity__c':0, 
                         'Price__c':0 }">
</aura:attribute>
<!--Input Form-->
<lightning:layout >
    <form>
        <fieldset class="slds-box slds-theme--default slds-container--small">
            <legend id="newexpenseform" class="slds-text-heading--small 
              slds-p-vertical--medium">
              Add Item
            </legend>
            <lightning:layoutItem >
            <ol>
                <lightning:input aura:id="input" label="Camping Item Name"
                     name="Name"
                     value="{!v.newItem.Name}"
                     required="true"/> 
                <lightning:input name="Quantity"
                                 aura:id="input"
                                 value="{!v.newItem.Quantity__c}" 
                                 label="Quantity" 
                                 type="number" 
                                 min="1" 
                                 messageWhenRangeUnderflow="Quantity should be greater than 0"/>
                <lightning:input name="Price"
                                 aura:id="input"
                                 value="{!v.newItem.Price__c}" 
                                 label="Price"
                                 formatter="currency"/>
                <lightning:input name="Packed"
                                 type="checkbox"
                                 label="Packed"
                                 aura:id="input"
                                 checked="{!v.newItem.Packed__c}"/>
            </ol>
            </lightning:layoutItem>
            <lightning:layoutItem >
                <lightning:button class="slds-m-top--medium" label="Submit" 
                                  onclick="{!c.clickCreateItem}" variant="brand">
                </lightning:button>
            </lightning:layoutItem>
        </fieldset>
    </form>
    <!--Display Items-->
    {!items}
            <aura:iteration items="{!v.items}" var="item">
                <c:campingListItem item="{!item}"></c:campingListItem>
            </aura:iteration>
</lightning:layout> 

And here is the code for my child component –

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes">
<aura:attribute name="item" type="Camping_Item__c" default="{ 
                                                            'sobjectType':'Camping_Item__c'
                                                            , 'Name':'Protien Bar',
                                                            'Packed__c':false ,
                                                            'Quantity__c':5,
                                                            'Price__c':25.0 }">
</aura:attribute>
<lightning:card title="Camping List">
    <p>{!v.item}</p>
    <p>Name : {!v.item.Name}</p>
    <p>Price : {!v.item.Price__c}</p>
    <p>Quantity : {!v.item.Quantity__c}</p>
    <p>Packed : {!v.item.Packed__c}</p>
    <p><lightning:formattedNumber value="{!v.item.Price__c}" style="currency"></lightning:formattedNumber></p>
    <p><lightning:formattedNumber value="{!v.item.Quantity__c}"></lightning:formattedNumber></p>
    <p><lightning:input name="Packed" label="Packed" type="toggle" checked="{!v.item.Packed__c}"></lightning:input></p>   
    <p><lightning:button label="Packed!" onclick="{!c.packItem}"></lightning:button></p>
</lightning:card>

The problem is it only shows me the value of {!v.item} that is the whole object and not the individual fields and I just cannot understand why. It also works when I use this component alone with a default value. Can anybody help me out?

Also adding the Javascript Controller –

({
clickCreateItem : function(component, event, helper) {
    var isValid=component.find("input").reduce( function( validSoFar,inputCmp){
        inputCmp.showHelpMessageIfInvalid();
        return validSoFar && inputCmp.get("v.validity").valid;
    }, true);
    if(isValid){
        console.log("working !");
        //Push newItem to items array
        var items=component.get("v.items");
        var newItem=JSON.stringify(component.get("v.newItem"));
        items.push(newItem);
        newItem="{'sobjectType':'Camping_Item__c','Name': '','Quantity__c': 0,'Price__c': 0,'Packed__c': false}";
        component.set("v.newItem",newItem);
        component.set("v.items",items);
    }
}

})

Here is the screenshot of the result enter image description here

Best Answer

When you pass an object from one component to another you don't need to stringify the data. In your code you were Stringify the 'newItem' before adding it to the items list. which in turn was passed to your child component as a string rather than an object. This is why {!v.item.Name} was not working as it works only for object not String. hence it was printing blank. In your controller class, remove the Json.stringify. newItem=JSON.stringify(component.get("v.newItem")); -----> newItem=component.get("v.newItem").