LWC Project: Update Parent Records from Child Page.

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

LWC component to update parent record from child

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.

Leave a Reply