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 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}”></template>
Name of my Contact:
{contact.data.fields.Name.value}
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:falsetag, 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 the api decorator. This is a standard parameter, and automatically gets the value of the current record.
- Instead of hard-coding, the recordId property for getRecord 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></targets>
<target>lightning__RecordPage</target>
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 and customerId)
- 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.