Lightning web Component updateRecord Example

Let us discuss here how to use lightning/uiRecordApi module adapters. This module includes wire adapters to record data and get default values to create records. It also includes JavaScript APIs to create, delete, update, and refresh records. one of the most of importance function is updateRecord that will be used to update the record in the database without using apex class.

Syntax 

the updateRecord syntax looks like below

import { updateRecord } from 'lightning/uiRecordApi';
updateRecord(recordInput: Record, clientOptions: Object): Promise<Record>
  • recordInput— (Required) A RecordInput object used to update the record. To create the object, call generateRecordInputForUpdate(record).
  • clientOptions— (Optional) To check for conflicts before you update a record, pass const clientOptions = {'ifUnmodifiedSince' : lastModifiedDate}. Get lastModifiedDate via a wire service adapter that returns a record object: const lastModifiedDate = record.fields.LastModifiedDate.value;.
  • A Promise object that resolves with the updated record. The record contains data for the fields in the record layout.

Create a Lightning Web component

create a new lightning web component using this SFDX command

sfdx force:lightning:component:create --type lwc -n updaterecord -d force-app/main/default/lwc

use this updaterecord.html code

<template>
    <lightning-card title="Update  Account Record" icon-name="standard:record">
        <div class="slds-m-around_medium">
            <lightning-input label="Name" onchange={handleNameChange} class="slds-m-bottom_x-small"></lightning-input>
            <lightning-input label="Annual Revenue" type="number" onchange={handleNameChange} class="slds-m-bottom_x-small"></lightning-input>

            <lightning-input label="Phone" type="phone" onchange={handleNameChange} class="slds-m-bottom_x-small"></lightning-input>
            <lightning-input label="Fax" type="phone" onchange={handleNameChange} class="slds-m-bottom_x-small"></lightning-input>

            <lightning-button label="Update  Account" variant="brand" onclick={updateAccount}></lightning-button>
        </div>
    </lightning-card>
</template>

Use this updaterecord .js code

import {
LightningElement,
track,api,wire
} from 'lwc';
import {
ShowToastEvent
} from 'lightning/platformShowToastEvent';
import ACCOUNT_OBJECT from '@salesforce/schema/Account';
import NAME_FIELD from '@salesforce/schema/Account.Name';
import ID_FIELD from '@salesforce/schema/Account.ID';

import ANNUALREV_FIELD from '@salesforce/schema/Account.AnnualRevenue';
import Fax_FIELD from '@salesforce/schema/Account.Fax';
import PHONE_FIELD from '@salesforce/schema/Account.Phone';


import {
getRecord,
updateRecord,
generateRecordInputForUpdate,
getFieldValue,
} from 'lightning/uiRecordApi';
import {
CurrentPageReference
} from 'lightning/navigation';


export default class Updaterecord extends LightningElement {
@api recordId;
@track accountId;
@track name = 'Demo Account';
@track annualrev = 0;
@track fax = '1231234345345';
@track phone = '1231234345345';

handleNameChange(event) {
    this.accountId = undefined;
    console.log('label values --->>' + event.target.label);
    if (event.target.label === 'Name') {
        this.name = event.target.value;
    }
    if (event.target.label === 'Annual Revenue') {
        this.annualrev = event.target.value;
    }
    if (event.target.label === 'Fax') {
        this.fax = event.target.value;
    }
    if (event.target.label === 'Phone') {
        this.phone = event.target.value;
    }

}


updateAccount() {
    let record = {
        fields: {
            Id: this.recordId,
            Name: this.name,
            AnnualRevenue:this.annualrev ,
            Fax:this.fax ,
            Phone:this.phone,
        },
    };
    updateRecord(record)
        // eslint-disable-next-line no-unused-vars
        .then(() => {
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Success',
                    message: 'Record Is Updated',
                    variant: 'sucess',
                }),
            );
        })
        .catch(error => {
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Error on data save',
                    message: error.message.body,
                    variant: 'error',
                }),
            );
        });


}

}

use this updaterecord.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="helloWorld">
    <apiVersion>45.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordPage</target>
    </targets>
</LightningComponentBundle>

 

Push changes to scratch org.

Push changes to scratch using this command and add this component to record page using lighting app builder

sfdx force:source:push

 

Understand  the code

The following JavaScript code will update the tracked properties when an input value is changed

handleNameChange(event) {
    this.accountId = undefined;
    console.log('label values --->>' + event.target.label);
    if (event.target.label === 'Name') {
        this.name = event.target.value;
    }
    if (event.target.label === 'Annual Revenue') {
        this.annualrev = event.target.value;
    }
    if (event.target.label === 'Fax') {
        this.fax = event.target.value;
    }
    if (event.target.label === 'Phone') {
        this.phone = event.target.value;
    }

}

The following code will call from the update button  which contains the record details for the update using the updateRecord function

updateAccount() {
    let record = {
        fields: {
            Id: this.recordId,
            Name: this.name,
            AnnualRevenue:this.annualrev ,
            Fax:this.fax ,
            Phone:this.phone,
        },
    };
    updateRecord(record)
        // eslint-disable-next-line no-unused-vars
        .then(() => {
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Success',
                    message: 'Record Is Updated',
                    variant: 'sucess',
                }),
            );
        })
        .catch(error => {
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Error on data save',
                    message: error.message.body,
                    variant: 'error',
                }),
            );
        });


}

 

 

 

Lightning web components Events

Let us discuss here how to use the lightning web component events to communicate between components. Lightning web components dispatch standard DOM events. Components can also create and dispatch custom events. Use events to communicate up the component containment hierarchy. Events in Lightning web components are built on DOM Events, a collection of APIs and objects available in every browser. we will be seeing here how to the events using the CustomEvent interface and publish-subscribe utility.

Create and Dispatch Events Using CustomEvent 

Let’s discuss here how to use to create events, using the CustomEvent interface. In Lightning web components, CustomEvent provides a more consistent experience across browsers, including Internet Explorer. It requires no setup or boilerplate, and it allows you to pass any kind of data via the detail property, which makes it flexible. Lightning web components implement the EventTarget interface, which allows them to dispatch events, listen for events, and handle events.
  1. To create an event, use the CustomEvent() constructor
    new CustomEvent('inptext', {
                detail: name
            });

     

  2. To dispatch an event, call the EventTarget.dispatchEvent()  method.
            this.dispatchEvent(selectEvent);
    

     

The CustomEvent constructor has one required parameter, which is a string indicating the event type. As a component author, you name the event type when you create the event. You can use any string as your event type. The below example shows how to use the CustomEvent constructor to fire the events and receive the events using the event object. In this example, we are firing the event from the eventsource component using the CustomEvent.Create a Lightning web component using the following SFDX command.

sfdx force:lightning:component:create --type lwc --componentname eventsource --outputdir force-app\main\default\lwc

Use the below eventsource.html code . in this code we have an input text field that will fire an event on onchange of the input text.

<template>
    <lightning-card title="Event Source">
        <div class="slds-m-around_medium">
            <lightning-input name="textVal" label="Enter Text" onchange={handleChange}></lightning-input>
        </div>
    </lightning-card>
</template>

use the below eventsource.js code and in this code, we have an handleChange function that will fire the event using the CustomEvent.

import {
    LightningElement
} from 'lwc';


export default class Eventsource extends LightningElement {
    handleChange(event) {
        event.preventDefault();
        const name = event.target.value;
        const selectEvent = new CustomEvent('inptext', {
            detail: name
        });
        this.dispatchEvent(selectEvent);
    }
}

Use the below eventsource.js-meta.xml code

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="helloWorld">
    <apiVersion>45.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordPage</target>
    </targets>
</LightningComponentBundle>

 

Now create an event container component that will receive the events form the eventsource. create lightning web components using the below SFDX command

sfdx force:lightning:component:create --type lwc --componentname eventcontainer --outputdir force-app\main\default\lwc

Use the below eventcontainer.html code. To listen for events, use an HTML attribute with the syntax oneventtype Since our event type inptext, the listeners are oninptext  and call the handler function on oninptext events  as shown below

        <c-eventsource oninptext={handleSelect}></c-eventsource>

Use the below eventcontainer.html code

<template>
    <div class="slds-m-around_medium">
        You Enter {valueInp}
        <c-eventsource oninptext={handleSelect}></c-eventsource>
    </div>
</template>

Use the eventcontainer.js code.  Receiving components access the data in the detail property in the event listener’s handler function.

import {
    LightningElement,
    track
} from 'lwc';


export default class Eventcontainer extends LightningElement {
     @track valueInp;
     handleSelect(event) {

         const textVal = event.detail;
         this.valueInp = textVal;
         console.log('textVaal' + textVal);
     }
}

Use the below eventcontainer.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="helloWorld">
    <apiVersion>45.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordPage</target>
    </targets>
</LightningComponentBundle>

The CustomEvent interface imposes no type requirements or structure on the detail property. However it’s important to send only primitive data. JavaScript passes all data types by reference except for primitives. If a component includes an object in its detail property, any listener can mutate that object without the component’s knowledge. This is a bad thing! It’s a best practice either to send only primitives, or to copy data to a new object before adding it to the detail property. Copying the data to a new object ensures that you’re sending only the data you want, and that the receiver can’t mutate your data.

Now if you see in the below image it shows the enter input data from the text box to container component. If you enter the text in the event source component, the CustomEvent will be fired and the same event details will be received at container component

 

 

Using publish-subscribe pattern

To communicate between components that aren’t in the same DOM tree, use a singleton library that follows the publish-subscribe pattern.In a publish-subscribe pattern, one component publishes an event. Other components subscribe to receive and handle the event. Every component that subscribes to the event receives the event. For example, if you add two components to a Lightning page in Lightning App Builder, use the pubsub module to send events between them. If you’re familiar with Aura, you may recognize that Aura application events follow the publish-subscribe pattern.

Please refer this link to get the publish-subscribe utility code.

Create a lightning web component using the below SFDX command.

sfdx force:lightning:component:create --type lwc --componentname publishsource --outputdir force-app\main\default\lwc

in this publish source component, we have an input text filed from where we are firing the event on input onchange events.

<template>
    <lightning-card title="Source" >
        <div class="slds-m-around_medium">
            <lightning-input type="text" onchange={handleChange} class="slds-m-bottom_small" label="Enter Text"></lightning-input>
        </div>
    </lightning-card>
</template>

Use the below publishsource.js code which will be publishing the event using publish-subscribe utility

import {
    LightningElement,
    wire
} from 'lwc';
import {
    CurrentPageReference
} from 'lightning/navigation';
import {
    fireEvent
} from 'c/pubsub';
export default class Publishsource extends LightningElement {
    @wire(CurrentPageReference) pageRef;

    handleChange(event) {
        fireEvent(this.pageRef, 'inputChangeEvent', event.target.value);
    }
}

In the above JavaScript file, we have two imports that are required to fire the events

import {
    CurrentPageReference
} from 'lightning/navigation';
import {
    fireEvent
} from 'c/pubsub';

Wire the current page reference using wire adapter as shown below

    @wire(CurrentPageReference) pageRef;

Fire the event using this below code .here inputChangeEvent is the event name.

        fireEvent(this.pageRef, 'inputChangeEvent', event.target.value);

use the below publishsource.js-meta.xml code

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="helloWorld">
    <apiVersion>45.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordPage</target>
    </targets>
</LightningComponentBundle>

create a publish receive that will listen the events .create a lightning web component using the below SFDX command.

sfdx force:lightning:component:create --type lwc --componentname publishreceiver --outputdir force-app\main\default\lwc

Use the below publishreceiver.html code

<template>
    <lightning-card title="Target">

        {inpVal}
    </lightning-card>
</template>

Use the below publishreceiver.js code that will listen to the events using the life cycle callbacks

import {
    LightningElement,
    track,
    wire
} from 'lwc';
import {
    CurrentPageReference
} from 'lightning/navigation';
import {
    registerListener,
    unregisterAllListeners,
    fireEvent
} from 'c/pubsub';

export default class Publishreceiver extends LightningElement {
      @track inpVal;
      @wire(CurrentPageReference) pageRef;

      connectedCallback() {
          // subscribe to inputChangeEvent event
          registerListener('inputChangeEvent', this.handleChange, this);
      }

      disconnectedCallback() {
          // unsubscribe from inputChangeEvent event
          unregisterAllListeners(this);
      }

      handleChange(inpVal) {
          this.inpVal = inpVal;
      }
}

use the below publishreceiver.js-meta.xml code

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="helloWorld">
    <apiVersion>45.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordPage</target>
    </targets>
</LightningComponentBundle>

 

Now you can able to see the event is firing from the source component which is handled by the target component as shown below.

 

 

Usage Of getPicklistValues wire adapter

Let us discuss here how to use the getPicklistValues wire adapter to get the picklist values for a specific field. Here is the sample code that explains how to use the getPicklistValues values.

Syntax 
import { LightningElement, wire } from 'lwc';
import { getPicklistValues } from 'lightning/uiObjectInfoApi';
import INDUSTRY_FIELD from '@salesforce/schema/Account.Industry';

export default class Example extends LightningElement {
    @wire(getPicklistValues, { recordTypeId: '012000000000000AAA', fieldApiName: INDUSTRY_FIELD })
    propertyOrFunction;
}

 

  • recordTypeId—(Required) The ID of the record type. Use the Object Info defaultRecordTypeId property, which is returned from getObjectInfo or getRecordUi.
  • fieldApiName—(Required) The API name of the picklist field on a supported object.
  • propertyOrFunction—A private property or function that receives the stream of data from the wire service. If a property is decorated with @wire, the results are returned to the property’s data property or error property. If a function is decorated with @wire, the results are returned in an object with a data property and an error property.

 

 Create Lightning web component

create a lightning web component using the following SFDX command. In this component, we will be showing the picklist values as a checkbox and as a dropdown using select

sfdx force:lightning:component:create --type lwc -n picklistvalues -d force-app/main/default/lwc

 

here is the picklistvalues.html  code

<template>
    <lightning-card title="Pick List Values as Checkbox" icon-name="custom:custom57">
        <template if:true={picklistValues.data}>
            <div class="slds-m-around_medium">
                <template for:each={picklistValues.data.values} for:item="item">
                    <lightning-input key={item.value} label={item.label} data-value={item.value} type="checkbox"></lightning-input>
                </template>
            </div>
        </template>
    </lightning-card>
    <lightning-card title="Select List " icon-name="custom:custom19">
        <template if:true={picklistValues.data}>
            <div class="slds-m-around_medium">

                <select>
                    <template for:each={picklistValues.data.values} for:item="item">
                        <option key={item.value}>{item.label}</option>
                    </template>
                </select>
            </div>
        </template>
    </lightning-card>
</template>

here is the picklistvalues.js code

import {
    LightningElement,
    wire
} from 'lwc';
import {
    getPicklistValues
} from 'lightning/uiObjectInfoApi';
import TYPE_FIELD from '@salesforce/schema/Account.Type';


export default class Picklistvalues extends LightningElement {
    @wire(getPicklistValues, {
        recordTypeId: '012000000000000AAA',
        fieldApiName: TYPE_FIELD,
    })
    picklistValues;
}

here is the picklistvalues.js-meta.xml code

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="helloWorld">
    <apiVersion>45.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordPage</target>
    </targets>
</LightningComponentBundle>

 

 Push changes to scratch org

Push changes to scratch using this command and add this component to record page using lighting app builder

And you can able to see the output as shown below.

 

 

 

Understand the Code

The following code will return the picklist values as a JavaScript object.

 

 @wire(getPicklistValues, {
        recordTypeId: '012000000000000AAA',
        fieldApiName: TYPE_FIELD,
    })
    picklistValues;

The following code will show the picklist values as an input checkboxes

<template if:true={picklistValues.data}>
            <div class="slds-m-around_medium">
                <template for:each={picklistValues.data.values} for:item="item">
                    <lightning-input key={item.value} label={item.label} data-value={item.value} type="checkbox"></lightning-input>
                </template>
            </div>
        </template>

The following code will show the values as a select list

 <select>
                    <template for:each={picklistValues.data.values} for:item="item">
                        <option key={item.value}>{item.label}</option>
                    </template>
                </select>

 

 

 

getObjectInfo Wire Adapter

Let us discuss here how to use this wire adapter getObjectInfo wire adaptor to get metadata about a specific object. The response includes metadata describing fields, child relationships, record type, and theme. Here is the sample Syntax on how to invoke the getObjectInfo wire adapter.

Syntax 

import { LightningElement, wire } from 'lwc';
import { getObjectInfo } from 'lightning/uiObjectInfoApi';
import ACCOUNT_OBJECT from '@salesforce/schema/Account';

export default class Example extends LightningElement {
    @wire(getObjectInfo, { objectApiName: ACCOUNT_OBJECT })
    propertyOrFunction;
}

 

  • objectApiName—(Required) A supported object.
  • propertyOrFunction—A private property or function that receives the stream of data from the wire service. If a property is decorated with @wire, the results are returned to the property’s data property or error property. If a function is decorated with @wire, the results are returned in an object with a data property and an error property.

Create Lightning web component

create a lightning web component using the following SFDX command.

sfdx force:lightning:component:create --type lwc -n ObjectInfo -d force-app/main/default/lwc

Use this ObjectInfo.html markup code

<template>
    <lightning-card title="Wire Get Object Info" icon-name="custom:custom67">
    <div class="slds-m-horizontal_medium">
        <template if:true={objectInfo.data}>
                <div class="scroller">
                    <pre>{objectInfoStr}</pre>
                </div>
            </template>
        </div>
        <template if:true={objectInfo.error}>
            Error .Please COntact your Admin .
        </template>
    </lightning-card>
</template>

Use this ObjectInfo.js code

import {
    LightningElement,
    api,
    track,
    wire
} from 'lwc';
import {
    getObjectInfo
} from 'lightning/uiObjectInfoApi';
import ACCOUNT_OBJECT from '@salesforce/schema/Account';

export default class ObjectInfo extends LightningElement {
    @api objectApiName;
    @track objectInfo;

    @wire(getObjectInfo, {
        objectApiName: '$objectApiName'
    })
    objectInfo;
    get objectInfoStr() {
        return this.objectInfo ?
            JSON.stringify(this.objectInfo.data, null, 2) :
            '';
    }
}

Use this ObjectInfo.js-meta.xml code

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="helloWorld">
    <apiVersion>45.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordPage</target>
    </targets>
</LightningComponentBundle>

Push changes to scratch org.

Push changes to scratch using this command and add this component to record page using lighting app builder

After adding the lightning web component to record page using the app builder. you can able to see the output as shown below

 

 

Understand the code

The following code returns the sobject data using the getObjectInfo wired adapter

 @api objectApiName;
    @track objectInfo;

    @wire(getObjectInfo, {
        objectApiName: '$objectApiName'
    })
    objectInfo;

 

The following markup will show the json data into UI

 <template if:true={objectInfo.data}>
                <div class="scroller">
                    <pre>{objectInfoStr}</pre>
                </div>
            </template>