Wiring up Lightning Web Components
In my previous post I investigated the basic structure of Lightning Web Components.
Now I’m going to dig deeper into one of the very crucial aspects of the framework: how you communicate with the backend. There are 3 ways to do so:
- Get a record(s) from the back-end
- Write a record to the back-end
- Call an APEX method on the back-end and get the result
Get a record(s) from the back-end
Get records from the back-end
Let’s start with the most simple solution:
import { LightningElement, wire } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';export default class Customer extends LightningElement { @wire (getRecord, {
recordId:'0031U00000GgfWQQAZ',
fields:['Contact.Name']
}
)
contact;
}
- The record is loaded into the
contact
property. - The previous line is a decorator; so this is the part of the property declaration. The
wire
function is applied to the contact property, it adds some extra functionality (you can read about decorators here). - The
wire
decorator has 2 arguments: getRecord
, which is a method imported from the lwc framework.- Arguments for the
getRecord
method: Id of the desired record and list of fields which you want to load.
When your component is loaded, it automatically gets the record from the server, and pushed it into the contact
property.
Let’s look at the UI side:
<template if:true={contact.data}>
Name of my Contact:
{contact.data.fields.Name.value}
</template>
If you want to display the Name
field value of your Contact, you go inside the data-structure: {contact.data.fields.Name.value}, because the records are coming as JavaScript objects.
You need to wrap the display part into an if:true
tag. The Contact record is not immediately loaded, so when your component is rendering, the contact.data
property doesn’t exist — which can cause a null-value error. You can also add a if:false
tag, where you can show a nice ‘Loading…’ message.
It’s important to know that the getRecord
function uses to Lightning Data Service. It gives you an extra security layer, and what is more important, dynamically refreshes records when they are changed by an other component on the UI.
Loading the current record
You may noticed that in the previous example we hard-coded a record Id. This is not a real-life situation. Usually, you want to load a record from the actual context of the user (let’s say, from the layout).
It’s easy:
import { LightningElement, wire, api } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';export default class Customer extends LightningElement {@api recordId;
@wire (getRecord, {
recordId:'$recordId',
fields:['Contact.Name']
}
)
contact;
}
2 things are changed:
- I added a
recordId
property, decorated with theapi
decorator. This is a standard parameter, and automatically gets the value of the current record. - Instead of hard-coding, the
recordId
property forgetRecord
is passed as$recordId
You should also make sure that your page is loadable on layout page, so make sure that your XML file has the following lines:
<targets>
<target>lightning__RecordPage</target>
</targets>
Function fun
You can also bind the loaded records to a function. So instead of directly pushing the value into a property, the getRecord
passes the result to a function.
@track name;
@track customerId;@wire (getRecord, {recordId : '$recordId',
fields: ['Stripe_Customer__c.Name',
'Stripe_Customer__c.Customer_Id__c']
})
loadCustomer({ error, data }) {
if (error) {
console.log('error:',
error.body.errorCode,
error.body.message
);
} else if (data) {
this.name = data.fields.Name.value;
this.customerId = data.fields.Customer_Id__c.value;
}
}
As you see, loadCustomer
function gets the result.
- If there is an error, it is logged
- If there is data, the function sets the class properties (
name
andcustomerId)
- What is nice about this that you don’t need to wrap your properties on the HTML side into
if:true
tags anymore. Until they are not loaded, their value is simply null.
How about getters?
If you don’t want to write a function when loading data, and you also don’t want to wrap it on the HTML side…there is still an option! Use a getter.
Add a getter function to the first example:
get myContactName() {
if(this.contact.data) {
return this.contact.data.fields.Name.value
}
return 'Loading...'
}
And now, on the HTML side you can use you can use simply as
{myContactName}
instead of {contact.data.fields.Name.value}
Boom!
Sum it up
- You can get data from the server using
getRecord
function. - You need to bind it to a class property or to a function using the
wire
decorator - You can use different strategies to find out if your record is loaded: you can check it on the HTML side, or you can use a getter.
In the next post I’ll write about how to communicate with APEX.