More about LWC, LDS, UI API and Decorators.

In the last post, we discussed about LWC, @track decorator and Apex Imperative Method technique. In this post, we will go little deeper to know about other Decorators such as @api and @wire.

Aura components and Lightning web components share the same underlying services Lightning Data Service, User Interface API etc. We will see how LDS(Lightning Data Service) and UI API work with LWC.
We will be creating 2 LWCs (lwcwithlds, createContact) to cover these concepts. Let’s get started.

lwcwithlds” LWC has two sections. The first section of displays Account data using LDS and also has inline edit within it. The recordId and objectApiName are declared as @api decorators.

Generally the api decorator is used for Parent-to-child inter-component communication. In this case, the Flexi Page(Account Record page) provides the recordId and objectApiName to this web component. Also one more thing to mention here is the fields are defined using dynamic schema approach. The syntax for the same is below:

fields = ['Name', 'Industry', 'AccountNumber'];

Another approach could be using Static Schema also can used as below:

import NAME_FIELD from '@salesforce/schema/Account.Name';  
import INDUSTRY_FIELD from '@salesforce/schema/Account.Industry';   import ACCOUNTNUMBER_FIELD from '@salesforce/schema/Account.AccountNumber';       

The second section of the component contains another child LWC “createContact”. This is to create Contact for the Account using LDS. Good thing here is; Record creation can be achieved without writing Server side code which is a well known forte of Lightning Design system. Here we are using @api decorator for “accountid”. The value of accountid passes from parent component “lwswithlds”. In order to create record, UI API can be used as below.

import { createRecord } from ‘lightning/uiRecordApi’;

To know more about User Interface API, refer the link given below. https://developer.salesforce.com/docs/atlas.en-us.uiapi.meta/uiapi/ui_api_resources_records_create.htm

Success/Error message is being shown using Lightning Toast.  

import { ShowToastEvent } from ‘lightning/platformShowToastEvent’;

Fields and Object name are referenced using Static Schema as explained above. Advantage of static schema approach is it respects referential integrity that means the fields and Object name is validated during Compilation time.  

The third section of the Component, renders all the related contacts for that specific account. Contacts are fetched from the server using Apex Wire Function with parameters. Yes you guess it right, we are using @wire decorator here.

import getContactList from '@salesforce/apex/ContactSearchController.getContactList'; 
           
//Call Apex method using Wire Decorator with a Parameter
@wire(getContactList, { accId: '$recordId' }) contacts;     

Code Snippet for lwswithlds.html

<template>
    <lightning-card title="Account Record Form using LDS (Dynamic)" icon-name="standard:Account">

        <div class="slds-m-around_medium">
            <lightning-record-form object-api-name={objectApiName} record-id={recordId} fields={fields}></lightning-record-form>
        </div>
    </lightning-card>
    <lightning-card>    
        <template if:true={recordId}>
            <c-create-contact accountid={recordId}> </c-create-contact>
        </template>
    </lightning-card>
    
    <template if:true={contacts.data}>
        <lightning-card title="Related Contacts using Wire decorator" icon-name="standard:Contact">
            <table class="slds-table slds-table_bordered slds-table_striped">
                <thead>
                    <tr>
                        <th scope="col"><span class="slds-truncate">Name</span></th>
                        <th scope="col"><span class="slds-truncate">Contact Title</span></th>
                        <th scope="col"><span class="slds-truncate">Email</span></th>
                        <th scope="col"><span class="slds-truncate">Phone</span></th>
                    </tr>
                </thead>
                <tbody>
                    <template for:each={contacts.data} for:item="contact">
                        <tr key={contact.Id}>
                            <td>{contact.Name}</td>
                            <td>{contact.Title}</td>
                            <td>{contact.Email}</td>
                            <td>{contact.Phone}</td>
                        </tr>
                    </template>
                </tbody>
            </table>
        </lightning-card>
    </template>
    
</template>

Code Snippet for createContact.html

<template>
    <lightning-card title="Create Contact using LDS" icon-name="standard:record">
        <div class="slds-m-around_medium">
            <lightning-input label="Id" disabled value={contactId}></lightning-input>
            <lightning-input label="Last Name" onchange={handleNameChange} class="slds-m-bottom_x-small"></lightning-input>
            <lightning-input label="Account" value={accountid} class="slds-m-bottom_x-small"></lightning-input>
            <lightning-input label="Email" onchange={handleEmailChange} class="slds-m-bottom_x-small"></lightning-input>
            <lightning-input label="Phone" onchange={handlePhoneChange} class="slds-m-bottom_x-small"></lightning-input>
            <lightning-button label="Create Contact" variant="brand" onclick={createContact}></lightning-button>
        </div>
    </lightning-card>    
</template> 


Code Snippet for lwswithlds.js

import { LightningElement, api, wire } from 'lwc';
import getContactList from '@salesforce/apex/ContactSearchController.getContactList';

export default class Lwcwithlds extends LightningElement {
     // Flexipage provides recordId and objectApiName
     @api recordId;
     @api objectApiName;
     fields = ['Name', 'Industry', 'AccountNumber'];
     //Call Apex method using Wire Decorator with a Parameter
     @wire(getContactList, { accId: '$recordId' })
     contacts;
} 

Code Snippet for createContact.js

import { LightningElement, track, api } from 'lwc';
//To show succes/error message using Lightning Toast
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
//Create Record using User Interface API
import { createRecord } from 'lightning/uiRecordApi';
import CONTACT_OBJECT from '@salesforce/schema/Contact';
import NAME_FIELD from '@salesforce/schema/Contact.LastName';
import EMAIL_FIELD from '@salesforce/schema/Contact.Email';
import PHONE_FIELD from '@salesforce/schema/Contact.Phone';
import ACCOUNTID_FIELD from '@salesforce/schema/Contact.AccountId';

export default class CreateContact extends LightningElement {
    @track contactId;
    //Account Id passed from Parent to Child Component using API decorator.
    @api accountid;

    name = '';
    email = '';
    phone = '';    
    

    handleNameChange(event) {
        this.contactId = undefined;
        this.name = event.target.value;
    }

    handleEmailChange(event) {
        this.email = event.target.value;
    }

    handlePhoneChange(event) {
        this.phone = event.target.value;
    }

    createContact() {
        const fields = {};
        fields[NAME_FIELD.fieldApiName] = this.name;
        fields[EMAIL_FIELD.fieldApiName] = this.email;
        fields[PHONE_FIELD.fieldApiName] = this.phone;
        fields[ACCOUNTID_FIELD.fieldApiName] = this.accountid;
        const recordInput = { apiName: CONTACT_OBJECT.objectApiName, fields };
        createRecord(recordInput)
            .then(contact => {
                this.contactId = contact.id;
                this.dispatchEvent(
                    new ShowToastEvent({
                        title: 'Success',
                        message: 'Contact created',
                        variant: 'success',
                    }),
                );
            })
            .catch(error => {
                this.dispatchEvent(
                    new ShowToastEvent({                        
                        title: 'Error creating record',
                        message: error.message,
                        variant: 'error',
                    }),
                );
            });
    }
}

Code Snippet for ContactSearchController.cls

public with sharing class ContactSearchController {   @AuraEnabled(cacheable=true)
    public static List<Contact> getContactList(Id accId) {
        system.debug('accId is:'+ accId);
        return [SELECT Id, Name, Title, Phone, Email FROM Contact where AccountId = :accId];
    }

}

The code is available on the following github link. The components also need to be pushed to Salesforce before it can be used. Steps to push the components are already explained in the previous post. Once we have the component avaible in Salesforce, we have created an Account Record to page to verify and see how it looks.

New Component
Account Record Page
Contact info for Contact Creation
Contact Created successfully

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.