Lightning Web Components
LWC Project: Update Parent Records from Child Page.
A Lighting web component which will allow user to update parent details from child record. What does that mean? Example: On Opportunity we have custom parents object Parent Object 1, Parent Object 2 and we want to update their details from child(Opportunity) it self.NOTE: Using standard Related Record component we can update parent record details from child.
Demo
Code Files
Get all parent of any salesforce object dynamically
@AuraEnabled
public static Map < String, String > getParentObjects(String childObject) {
Map < String, String > mapParentObjects = new Map < String, String > ();
String SobjectApiName = childObject;
Map < String, Schema.SObjectType > schemaMap = Schema.getGlobalDescribe();
for (Schema.SobjectField fldMap: schemaMap.get(SobjectApiName).getDescribe().fields.getMap().Values()) {
String customField = fldMap.getDescribe().getName();
if (customField.endsWith('__c') && fldMap.getDescribe().getType() == Schema.DisplayType.REFERENCE) {
List < SObjectType > refObjs = fldMap.getDescribe().getReferenceTo();
String objectName = String.valueOf(refObjs[0]);
mapParentObjects.put(getObjectLabel(objectName), objectName);
}
}
return mapParentObjects;
} Dynamically get all updatable fields of any object in Apex
@AuraEnabled
public static Map < String, String > getUpdatableFields(String strObjectName) {
Map < String, Schema.SObjectType > detail = Schema.getGlobalDescribe();
Map < String, String > mapOfPicklistTypeFields = new Map < String, String > ();
for (Schema.SObjectField fields: detail.get(strObjectName).getDescribe().fields.getMap().Values()) {
If(fields.getDescribe().isAccessible() && fields.getDescribe().isCreateable() && fields.getDescribe().isUpdateable()) {
mapOfPicklistTypeFields.put(fields.getDescribe().getLabel(), fields.getDescribe().getName());
}
}
return mapOfPicklistTypeFields;
} Method of get object label
public static String getObjectLabel(String objectName) {
Map < String, SObjectType > sObjects = Schema.getGlobalDescribe();
return sObjects.get(objectName).getDescribe().getLabel();
} JAVASCRIPT
@api recordId;
@api objectApiName; Apex Class
public with sharing class UpdateParentFromChild {
@AuraEnabled
public static Map < String, String > getParentObjects(String childObject) {
Map < String, String > mapParentObjects = new Map < String, String > ();
String SobjectApiName = childObject;
Map < String, Schema.SObjectType > schemaMap = Schema.getGlobalDescribe();
for (Schema.SobjectField fldMap: schemaMap.get(SobjectApiName).getDescribe().fields.getMap().Values()) {
String customField = fldMap.getDescribe().getName();
if (customField.endsWith('__c') && fldMap.getDescribe().getType() == Schema.DisplayType.REFERENCE) {
List < SObjectType > refObjs = fldMap.getDescribe().getReferenceTo();
String objectName = String.valueOf(refObjs[0]);
mapParentObjects.put(getObjectLabel(objectName), objectName);
}
}
return mapParentObjects;
}
public static String getObjectLabel(String objectName) {
Map < String, SObjectType > sObjects = Schema.getGlobalDescribe();
return sObjects.get(objectName).getDescribe().getLabel();
}
@AuraEnabled
public static Map < String, String > getUpdatableFields(String strObjectName) {
Map < String, Schema.SObjectType > detail = Schema.getGlobalDescribe();
Map < String, String > mapOfPicklistTypeFields = new Map < String, String > ();
for (Schema.SObjectField fields: detail.get(strObjectName).getDescribe().fields.getMap().Values()) {
If(fields.getDescribe().isAccessible() && fields.getDescribe().isCreateable() && fields.getDescribe().isUpdateable()) {
mapOfPicklistTypeFields.put(fields.getDescribe().getLabel(), fields.getDescribe().getName());
}
}
return mapOfPicklistTypeFields;
}
} LWC HTML
<template>
<div class="slds-card">
<lightning-combobox class="slds-grid slds-col slds-size_2-of-3"
name="parentObjects"
label="Select Parent Object"
value={value}
placeholder="Select Object"
options={options}
onchange={handleParentObjectChange} >
</lightning-combobox>
<div lwc:if={showEditForm} >
<lightning-record-edit-form object-api-name={parentObject} record-id={parentRecordId} onsuccess={handleSuccess} onerror={handleError}>
<template for:each={fieldsToUpdate} for:item="currentItem" for:index="index">
<!-- <lightning-layout-item key={currentItem.value} size="6" class="slds-grid">
<lightning-input-field field-name={currentItem.value}> </lightning-input-field>
</lightning-layout-item> -->
<lightning-input-field key={currentItem.value} field-name={currentItem.value}> </lightning-input-field>
</template>
<div class="slds-var-m-top_medium">
<lightning-button variant="brand" type="submit" label="Update"></lightning-button>
</div>
</lightning-record-edit-form>
</div>
</div>
</template> LWC JS
import { LightningElement, track, api, wire } from 'lwc';
import { ShowToastEvent } from "lightning/platformShowToastEvent";
import getParentObjects from '@salesforce/apex/UpdateParentFromChild.getParentObjects';
import getUpdatableFields from '@salesforce/apex/UpdateParentFromChild.getUpdatableFields';
import { getRecord } from "lightning/uiRecordApi";
export default class UpdateParentFromChild extends LightningElement {
@track options = [];
@track fieldsToUpdate = [];
@track showEditForm = false;
@api recordId;
@api objectApiName;
@track parentRecordId;
@track childRecordData;
connectedCallback() {
this.getParentObjects();
this.childRecordId = this.recordId;
console.log('objectApiName 1' , this.objectApiName);
}
@wire(getRecord, { recordId: "$childRecordId", layoutTypes: ["Full"], modes: ["View"] })
childData({ error, data }) {
if (data) {
this.childRecordData = data;
} else (
console.log('error in getting company url',error)
)
}
getParentObjects() {
getParentObjects({ childObject: this.objectApiName })
.then(result => {
this.options = [];
for (let key in result ) {
this.options.push({ label: key, value: result[key] });
}
})
.catch(error => {
this.showToast('Error', 'Error getting parent objects', 'error')
});
}
handleParentObjectChange(event) {
this.showEditForm = false;
this.parentRecordId = '';
this.parentObject = event.detail.value;
this.parentRecordId = this.childRecordData.fields[this.parentObject].value
this.getUpdatableFields(this.parentObject);
}
getUpdatableFields() {
getUpdatableFields({ strObjectName: this.parentObject})
.then(result => {
this.fieldsToUpdate = [];
for (let key in result ) {
this.fieldsToUpdate.push({ label: key, value: result[key] });
}
if(this.parentRecordId && this.parentRecordId != '') {
this.showEditForm = true;
} else {
this.showToast('Warning', 'Parent not linked', 'warning')
}
})
.catch(error => {
this.showToast('Error', 'Error getting updatable fields', 'error')
});
}
handleSuccess() {
this.showToast('Success', 'Child record updated', 'success')
}
handleError() {
this.showToast('Error', 'Error in updating child record', 'error')
}
showToast(title, message, variant) {
const evt = new ShowToastEvent({
title: title,
message: message,
variant: variant,
});
this.dispatchEvent(evt);
}
} LWC XML
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>62.0</apiVersion>
<isExposed>true</isExposed>
<masterLabel>Update Parent Record</masterLabel>
<targets>
<target>lightning__RecordPage</target>
</targets>
</LightningComponentBundle> Building something similar?
Explore more reusable LWC patterns or Apex fundamentals to go with it.