Sunday, 26 November 2017

Lightning Data Service Basics: Handle Record Changes and Errors

Lightning Data Service Basics: Handle Record Changes and Errors

accEdit Component Code


<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global" >
<aura:attribute name="record" type="Object" 
      description="The record object to be displayed"/>
    <aura:attribute name="simpleRecord" type="Object" 
      description="A simplified view record object to be displayed"/>
    <aura:attribute name="recordSaveError" type="String" 
      description="An error message bound to force:recordData"/>
    
    <force:recordData aura:id="accountRecord"
        layoutType="FULL"
        recordId="{!v.recordId}"
        targetError="{!v.recordSaveError}"
        targetRecord="{!v.record}"
        targetFields="{!v.simpleRecord}"
        recordUpdated="{!c.recordUpdated}"
        fields="Name"
        mode="EDIT"/>
    
    <!-- Display an editing form -->
        <div class="Record Details">
            <lightning:card iconName="action:edit" title="Edit Account">
                <div class="slds-p-horizontal--small">
                    <lightning:input label="Account Name" value="{!v.accountRecord.Name}"/>
                    <br/>
                    <lightning:button label="Save Account" variant="brand" onclick="{!c.handleSaveRecord}" />
                </div>
            </lightning:card>
        </div>
    <!-- Display Lightning Data Service errors, if any -->
    <aura:if isTrue="{!v.recordSaveError}">

        <div class="recordError">
            {!v.recordSaveError}</div>
    </aura:if>
</aura:component>

accEdit Controller Component


({
    recordUpdated: function(component, event, helper) {
        var eventParams = event.getParams();
        if(eventParams.changeType === "CHANGED") {
            // get the fields that are changed for this record
            var changedFields = eventParams.changedFields;
            //console.log('Fields that are changed: ' + JSON.stringify(changedFields));
            // record is changed so refresh the component (or other component logic)
            var resultsToast = $A.get("e.force:showToast");
            resultsToast.setParams({
                "title": "Saved",
                "message": "The record was updated."
            });
            resultsToast.fire();
        } else if(eventParams.changeType === "LOADED") {
        } else if(eventParams.changeType === "REMOVED") {
           
        } else if(eventParams.changeType === "ERROR") {
         
        }
    },
    handleSaveRecord: function(cmp, event, helper) {
        cmp.find("accountRecord").saveRecord($A.getCallback(function(saveResult) {
            if (saveResult.state === "ERROR") {
                var errMsg = "";
                for (var i = 0; i < saveResult.error.length; i++) {
                    errMsg += saveResult.error[i].message + "\n";
                }
                cmp.set("v.recordSaveError", errMsg);

            } else {
                cmp.set("v.recordSaveError", "");

            }
        }));}
    
})

Note:If you keep getting this error "The 'accEdit' Lightning Component JS Controller does not appear to be setting 'v.recordSaveError' with an error message" then make sure in handleSaveRecord function you are using "cmp" not any other name.

Wednesday, 22 November 2017

Lightning Data Service Basics: Manipulate Records with force:recordData

Lightning Data Service Basics: Manipulate Records with force:recordData

Manipulation of records with forcerecordData featsure. You can do insert update and delete using this.

accDisplay Component Code


<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global" >
<aura:attribute name="record" type="Object" 
      description="The record object to be displayed"/>
    <aura:attribute name="simpleRecord" type="Object" 
      description="A simplified view record object to be displayed"/>
    <aura:attribute name="recordError" type="String" 
      description="An error message bound to force:recordData"/>
    
    <force:recordData aura:id="accountRecord"
        layoutType="FULL"
        recordId="{!v.recordId}"
        targetError="{!v.recordError}"
        targetRecord="{!v.record}"
        targetFields ="{!v.simpleRecord}"
        mode="VIEW"/>
    <!-- Display a lightning card with details about the record -->
    <div class="Record Details"> 
        <lightning:card iconName="standard:account" title="{!v.accountRecord.Name}" >
            <div class="slds-p-horizontal--small">
                <p class="slds-text-heading--small">
                    <lightning:formattedText title="Name" value="{!v.accountRecord.Name}" /></p>
                <p class="slds-text-heading--small">
                    <lightning:formattedText title="Industry" value="{!v.accountRecord.Industry}" /></p>
                <p class="slds-text-heading--small">
                    <lightning:formattedText title="Description" value="{!v.accountRecord.Description}" /></p>
                <p class="slds-text-heading--small">
                    <lightning:formattedPhone title="Phone" value="{!v.accountRecord.Phone}" /></p>
            </div>
        </lightning:card>
    </div>
        
    <!-- Display Lightning Data Service errors, if any -->
    <aura:if isTrue="{!not(empty(v.recordError))}">
        <div class="recordError">
            {!v.recordError}</div>
    </aura:if>
</aura:component>

accEdit Component Code


<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global" >
<aura:attribute name="record" type="Object" 
      description="The record object to be displayed"/>
    <aura:attribute name="simpleRecord" type="Object" 
      description="A simplified view record object to be displayed"/>
    <aura:attribute name="recordError" type="String" 
      description="An error message bound to force:recordData"/>
    
    <force:recordData aura:id="accountRecord"
        layoutType="FULL"
        recordId="{!v.recordId}"
        targetError="{!v.recordError}"
        targetRecord="{!v.record}"
        targetFields ="{!v.simpleRecord}"
        fields="Name"
        mode="EDIT"/>
    
    <!-- Display an editing form -->
        <div class="Record Details">
            <lightning:card iconName="action:edit" title="Edit Account">
                <div class="slds-p-horizontal--small">
                    <lightning:input label="Account Name" value="{!v.accountRecord.Name}"/>
                    <br/>
                    <lightning:button label="Save Account" variant="brand" onclick="{!c.handleSaveRecord}" />
                </div>
            </lightning:card>
        </div>
</aura:component>

accEdit Controlller Js Code


({
    handleSaveRecord: function(component, event, helper) {
        component.find("accountRecord").saveRecord($A.getCallback(function(saveResult) {
            if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
                console.log("Save completed successfully.");
            } else if (saveResult.state === "INCOMPLETE") {
                console.log("User is offline, device doesn't support drafts.");
            } else if (saveResult.state === "ERROR") {
                console.log('Problem saving record, error: ' + 
                           JSON.stringify(saveResult.error));
            } else {
                console.log('Unknown problem, state: ' + saveResult.state + ', error: ' + JSON.stringify(saveResult.error));
            }
        }));}
})

Monday, 20 November 2017

Lightning Components Basics: Connect to Salesforce with Server Side Controllers

Lightning Components Basics: Connect to Salesforce with Server Side Controllers

Campaign List Component Code


<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: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">
<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>
    <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 Code


({
     // 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);
    },
    
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("item");
            helper.createItem(component, addItm);
            var newCampingItem = component.get("v.newItem");
            var campings = component.get("v.items");
            var item = JSON.parse(JSON.stringify(newCampingItem));
            campings.push(item);
            component.set("v.items",campings);
            component.set("v.newItem",{ 'sobjectType': 'Camping_Item__c','Name': '','Quantity__c': 0,
                                           'Price__c': 0,'Packed__c': false });
        }


}
})

Campaign  List Helper Code

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

Sunday, 19 November 2017

Lightning Components Basics: Input Data using Forms

Lightning Components Basics: Input Data using Forms

Campaign Header Component Code:


<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,force:lightningQuickAction" access="global" >
    <lightning:layout class="slds-page-header slds-page-header--object-home">
        <lightning:layoutItem>
            <lightning:icon iconName="action:goal" alternativeText="My Camping List"/>
        </lightning:layoutItem>
        <lightning:layoutItem padding="horizontal-small">
            <div class="page-section page-header">
                <h1 class="slds-text-heading--label">Campaign List</h1>
                <h2 class="slds-text-heading--medium">My Campaign List</h2>
            </div>
        </lightning:layoutItem>
    </lightning:layout>

</aura:component>

Campaign List Component Code:


<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,force:lightningQuickAction" access="global" >
<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">
<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>
    <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>

Campaign List Controller Code


({
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 newCampingItem = component.get("v.newItem");
            var campings = component.get("v.items");
            var item = JSON.parse(JSON.stringify(newCampingItem));
            campings.push(item);
            component.set("v.items",campings);
            component.set("v.newItem",{ 'sobjectType': 'Camping_Item__c','Name': '','Quantity__c': 0,
                                           'Price__c': 0,'Packed__c': false });
        }

}
})

Campaign List Item Code


<aura:component implements="flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global" >
<aura:attribute name="item" type="Camping_Item__c" required="true"/>
<aura:attribute name="Name" type="String"/>
    <p>Hello! {!v.item.Name}</p>
<aura:attribute name="Price" type="String"/>
    <p>Price:
<lightning:formattedNumber value="{!v.item.Price__c}" style="currency"/>
    </p>
    <aura:attribute name="Quantity" type="String"/>
    <p>Price:
<lightning:formattedNumber value="{!v.item.Quantity__c}" style="Number"/>
    </p>
    <aura:attribute name="Packed" type="String"/>
    <p>
        <lightning:input type="toggle"                           
                         label="Packed?"                          
                         name="Packed"                        
                         checked="{!v.item.Packed__c}" />
     </p>
    <div>
<lightning:button label="Packed!"
            onclick="{!c.packItem}"/>
    </div>
    
</aura:component>

Happy Coding !!!