Sunday, 10 December 2017

Lightning Components Basics: Connect Components with Events

Lightning Components Basics: Connect Components with Events 

CampingListComp:


<aura:component controller="CampingListController"
implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,force:lightningQuickAction" access="global" >
<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[]"/>
    <!--<aura:attribute name="newItem" type="Camping_Item__c" default="{ 'sobjectType': 'Camping_Item__c',
                        'Name': '',
                        'Quantity__c': 0,                                          
                        'Price__c': 0,
                        'Packed__c': false }"/>-->
    <ol>
        <li>Bug Spray</li>
        <li>Bear Repellant</li>
        <li>Goat Food</li>
    </ol> 
    <!-- PAGE HEADER -->
    
    <c:campingHeader />
    <lightning:layout >
<lightning:layoutItem padding="around-small" size="6">
<c:campingListForm />
        </lightning:layoutItem>
    </lightning:layout>

    
    <c:campingHeader />

<div class="slds-card slds-p-top--medium">
        <header class="slds-card__header">
            <h3 class="slds-text-heading--small">Items</h3>
        </header>
         
        <section class="slds-card__body">
            <div id="list" class="row">
                <aura:iteration items="{!v.items}" var="items">
                    <c:campingListItem item="{!item}"/>
                </aura:iteration>
            </div>
        </section>
    </div>

</aura:component>

CampaignListController:


({
     // 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 (state === "SUCCESS") {
                component.set("v.items", response.getReturnValue());
            }
            else {
                console.log("Failed with state: " + state);
            }
        });
    
        // Send action off to be executed
        $A.enqueueAction(action);
    },
     handleAddItem: function(component, event, helper) {
         var newItem = event.getParam("item");
         var action = component.get("c.saveItem");
         action.setParams({"item": newItem});
action.setCallback(this, function(response){
                var state = response.getState();
                if (component.isValid() && state === "SUCCESS") {
                    // all good, nothing to do.
                }
            });
            $A.enqueueAction(action);
       
     }
})

Camping List Form Component

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global" >
<aura:attribute name="newItem" type="Camping_Item__c" default="{ 'sobjectType': 'Camping_Item__c',
                        'Name': '',
                        'Quantity__c': 0,                                          
                        'Price__c': 0,
                        'Packed__c': false }"/>
    <aura:registerEvent name="addItem" type="c:addItemEvent"/> 
    <lightning:layout >
        <lightning:layoutItem padding="around-small" size="6">
<div aria-labelledby="newcampaignform">
                <fieldset class="slds-box slds-theme--default slds-container--small">
    <legend id="newcampaignform" class="slds-text-heading--small slds-p-vertical--medium">
                    Add Campaign List
                    </legend> 
                    <form class="slds-form--stacked">
                        <lightning:input aura:id="campaignform" label="Campaign Item Name"
                         name="campaignitemname"
                         value="{!v.newItem.Name}"
                         required="true"/>
                        <lightning:input type="number" aura:id="expenseform" label="Quantity"
                         name="campaignitemprice"
                         min="1"
                         formatter="number"
                         step="0.1"
                         value="{!v.newItem.Quantity__c}"
                         messageWhenRangeUnderflow="Enter quantity that's at least 1."/>
<lightning:input type="number" aura:id="expenseform" label="Price"
                         name="campaignitemprice"
                         min="0.1"
                         formatter="currency"
                         step="0.01"
                         value="{!v.newItem.Price__c}"
                         messageWhenRangeUnderflow="Enter an amount that's at least $0.10."/>
<lightning:input type="checkbox" aura:id="expenseform" label="Packed?" 
                         name="expreimbursed"
                         checked="{!v.newItem.Packed__c}"/>
<lightning:button label="Create Camping" class="slds-m-top--medium"
                                 variant="brand" onclick="{!c.clickCreateItem}"/>
                    </form>
                </fieldset>
            </div>
            
</lightning:layoutItem>
    </lightning:layout>
</aura:component>

Camping List Form Controller

({
clickCreateItem: function(component, event, helper) {
var validCamping = component.find('campingform').reduce(function (validSoFar, inputCmp) {
            // Displays error messages for invalid fields
            inputCmp.showHelpMessageIfInvalid();
            return validSoFar && inputCmp.get('v.validity').valid;
        }, true);
if(validCamping){
            var addItm = event.getParam("v.newItem");
            helper.createItem(component, addItm);
        }
}
})

Camping List Form Helper

({
addItem : function(component, campaign) {
        var createEvent = component.getEvent("addItem");
     createEvent.setParams({ "item": campaign });
    createEvent.fire();
component.set("v.newItem",{ 'sobjectType': 'Camping_Item__c',
                    'Name': '',
                    'Quantity__c': 0,
                    'Price__c': 0,
                    'Packed__c': false });
}
})

AddItemEvent

Create File | New | Lightning Event,
<aura:event type="COMPONENT">
    <aura:attribute name="item" type="Camping_Item__c"/> 
</aura:event>

7 comments:

  1. I actually get the error:
    The campingList JavaScript controller isn't pushing the new record to the 'items' value provider to set the new array in the component

    What is wrong?

    ReplyDelete
    Replies
    1. You can update the "handleAddItem" method as below in CampaignListController js

      handleAddItem: function(component, event, helper) {
      var newItem = event.getParam("item");
      var action = component.get("c.saveItem");
      action.setParams({"item": newItem});
      action.setCallback(this, function(response){
      var state = response.getState();
      if (component.isValid() && state === "SUCCESS") {
      var items = component.get("v.items");
      items.push(item);
      component.set("v.items",items);
      }
      });
      $A.enqueueAction(action);

      }

      Delete
  2. its shows me error
    Challenge not yet complete... here's what's wrong:
    Found the target XML.

    ReplyDelete
    Replies
    1. Can you tell me what is wrong and where is the target XML

      Delete
  3. Oh great , Thank you for this code, it worked fine for me. I really appreciate you.

    ReplyDelete
  4. Doesn't work!
    But try this ==> https://salesforce.stackexchange.com/questions/155287/the-campinglist-javascript-controller-isnt-setting-the-item-as-a-parameter-or/156728


    I ended up moving the createItem function from my helper function to the CampingListController, since Trailhead does not "ask" us to split the createItem into a helper function.


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

    },

    createItem: function(component, newItem) {
    var action = component.get("c.saveItem");
    action.setParams({
    "item": newItem
    });
    action.setCallback(this, function(response){
    var state = response.getState();
    if (component.isValid() && state === "SUCCESS") {
    var items = component.get("v.items");
    items.push(response.getReturnValue());
    component.set("v.items", items);
    }
    });
    $A.enqueueAction(action);
    },

    ReplyDelete
  5. It is very helpful for resolving the error:
    The campingList JavaScript controller isn't pushing the new record to the 'items' value provider to set the new array in the component

    ReplyDelete