In this blog, we’ll explore how data from Salesforce can be fetched using the GraphQL API and displayed in UI by using LWC Component.
What is the GraphQL API?
The launch of the Salesforce GraphQL API introduces a unique development by Salesforce in experience APIs. The Salesforce GraphQL API is commonly available as of Winter ’23.
GraphQL is the standard query language for APIs and the runtime environment for fetching data into queries. This is a new paradigm for sending and receiving data that provides a single endpoint for the developer to retrieve all the data needed in one request. This API allows developers to interact with the Salesforce platform through GraphQL API and fetch Salesforce records.
When to Use GraphQL? :
Using GraphQL, it is possible to create an API for a business that has a database of products and customers. This API would allow customers to access and modify their own data, as well as browse and purchase products. The flexible nature of GraphQL allows customers to make queries and mutations to retrieve or update their data, such as requesting a list of past orders or updating their shipping address. The API could also enable customers to search for and purchase products, like requesting a list of products within a certain price range or searching for a specific product by name. In comparison to traditional REST APIs, GraphQL can be a more effective tool for building APIs that allow customers to interact with a business in a flexible and efficient manner.
Benefits of GraphQL API :
The Salesforce GraphQL API provides benefits for developers by
- Field selection
- Resource aggregation
- Schema introspection
- sObject query ability
- more performant than traditional REST APIs.
GraphQL Schema:
GraphQL server uses a schema to define the structure of the available data. The schema outlines a hierarchy of types with fields for each type. Further, it details explicitly which queries and mutations developers have executed to get the required result.
Schema of Salesforce Data:
Altair GraphQL Client is an open-source tool that helps you debug GraphQL queries and implementations. The client enables access to schema documentation via introspection through a rich interface.
In the above GraphQL Query, we get the schema of how salesforce data will be fetched.
Salesforce GraphQL Query :
In the above GraphQL API, we get all the Account records with the required fields and all related contact and opportunity records.
Get Data From GraphQL API Using LWC
APEX Code :
- Get Auth token and HTTP Response. We can get auth token and responses from the Apex class and pass them to the LWC JS.
Constant variable Declaration :
public class Constants {
public static String POST = 'POST';
public static String PATCH = 'PATCH';
public static String GET = 'GET';
public static String AUTHORIZATION = 'Authorization';
public static String BEARER = 'Bearer ';
public static String BASIC = 'Basic ';
}
HTTP response Declaration :
public class RestAPIUtil {
public static HttpResponse getHTTP(String endPoint,Map<String,String> headers,string body){
HttpRequest request = new HttpRequest();
HttpResponse response = new HttpResponse();
Http http = new Http();
request.setMethod(Constants.GET);
request.setEndpoint(endpoint);
for(String header : headers.keySet()){
request.setHeader(header,headers.get(header));
}
try {
response = http.send(request);
return response;
} catch(System.CalloutException e) {
throw new GateWayException('Error Occured Get in Http call out',e);
}
}
public static HttpResponse postHTTP(String endpoint,Map<String,String> headers,String body){
HttpRequest request = new HttpRequest();
HttpResponse response = new HttpResponse();
Http http = new Http();
request.setMethod(Constants.POST);
request.setEndpoint(endpoint);
for(String header : headers.keySet()){
request.setHeader(header,headers.get(header));
}
request.setBody(body);
try {
response = http.send(request);
return response;
} catch(System.CalloutException e) {
throw new GateWayException('Error Occured in Post Http call out',e);
}
}
public class GateWayException extends Exception {}
}
Apex class for Get Access token :
public class ApiCallForGraphQL {
@AuraEnabled(cacheable = true)
public static Map<String, Object> getAccessToken(){
Map<String, String> headers = new Map<String,String>();
Map<String, Object> authResponse = new Map<String, Object>();
headers.put('Content-Type','application/x-www-form-urlencoded');
String clientId = '**********************************';
String clientSecret =’**********************************’;
String username = '**********************************';
String password = '**********************************';
String token = '**********************************';
String authEndpoint = 'https://**************.salesforce.com/services/oauth2/token';
String requestBody = 'grant_type=password&client_id=' + clientId + '&client_secret=' + clientSecret + '&username=' + username + '&password=' + password + token;
HttpResponse res = RestAPIUtil.postHTTP(authEndpoint,headers,requestBody);
String responseBody = res.getBody();
authResponse = (Map<String, Object>) JSON.deserializeUntyped(responseBody);
return authResponse;
}
}
LWC API Util Js :
Create the UtilApi.js file and export the following post request function.
export async function postData({ headers , apiEndpoint, apibody }) {
console.log('response in headers-->'+headers);
const response = await fetch( apiEndpoint, { method: 'POST', headers: headers, body: apibody });
if (!response.ok) {
throw Error(response.statusText);
}
return response.json();
}
Connect GraphQL to Salesforce
Using the Auth token and response received from Apex, we can get the Data from GraphQL API directly from LWC Js.
JS Code :
import { LightningElement } from 'lwc';
import { postData } from 'c/UtilApi;
import getAccessToken from '@salesforce/apex/ApiCallForGraphQL.getAccessToken';
export default class GetGraphQLQueryData extends LightningElement {
accesstoken = '';
instanceUrl = '';
gridData = [];
isLoading= true;
columns = [
{
type: "text",
fieldName: "Name",
label: "Name"
},
{
type: "text",
fieldName: "Rating",
label: "Rating"
},
{
type: "text",
fieldName: "Phone",
label: "Phone"
},
]
data = [];
connectedCallback() {
getAccessToken().then(result => {
if (result) {
this.accesstoken = result.access_token;
this.instanceUrl = result.instance_url;
let graphqlQuery = JSON.stringify({
query: "query accouts {\n uiapi {\nquery {\n Account(first: 100){\n edges {\n node {\n Id\n Name{value}\n Rating {value}\n Phone{value}\n }\n }\n }\n }\n }\n}",
variables: {}
});
let apiHeaders = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.accesstoken,
'Accept': 'application/json',
};
let graphQlEndPoint = this.instanceUrl + '/services/data/v54.0/graphql';
postData({ headers: apiHeaders, apiEndpoint: graphQlEndPoint, apibody: graphqlQuery }).then((data) => {
let tempData = [];
data.data.uiapi.query.Account.edges.map(acc => {
tempData.push({
Id: acc.node.Id,
Rating: acc.node.Rating.value,
Name: acc.node.Name.value.replace("&","&"),
Phone: acc.node.Phone.value,
});
})
this.data = tempData;
this.isLoading = false;
});
}
}).catch(error => {
this.error = error;
});
}
}
UI Code :
<template>
<lightning-card variant="Narrow" title="Accounts" icon-name="standard:account">
<template if:true={isLoading}>
<lightning-spinner alternative-text="Loading" size="large"></lightning-spinner>
</template>
<lightning-datatable key-field="id" data={data} columns={columns}>
</lightning-datatable>
</lightning-card>
</template>