What’s new today?
Wrapper Class gives extra flexibility to Salesforce developers. A wrapper or container class is a data structure that contains different objects or collections of objects as its members. We all have used it in Visualforce pages, Lightning Aura Component and now in Lightning Web Component.
These types of objects are generally nested objects.
But, as you know, since winter 20, security for immutable @api properties has been increased for LWC. Each Object’s elements are read-only to prevent modification so that the cache can’t be corrupted by references. If you try it, you will see this error :
[LWC component’s @wire target property or method threw an error during value provisioning. Original error:
[Cannot assign to read only property ‘Phone’ of object ‘#<Object>’]]
To fix it, you have to copy the elements using the spread operator (…), or Object.assign into a new object but you will remove the read-only properties of all top-level elements. If you want to change a property of an object in an object in an object etc… (nested object) it is not so easy and you have to copy all the nested object’s elements.
For every project I worked on, I got used to create in my LWC javascript utility lib the two functions below to simulate a custom Object.assign for nested objects.
/********************************************** * Two functions to set a value of nested items * key string descriptor inside an Object. **********************************************/ const setNestedKey = (obj, path, value) => { if (path.length === 1) { let key = path[0]; if (Array.isArray(obj)) { let table = [...obj]; table.splice(key, 1, value); obj = [...table]; return obj; } obj = { ...obj, [key]: value } return obj; } return setNestedKey(obj[path[0]], path.slice(1), value) } const assignObject = (obj, path, value) => { // Protect against being something unexpected obj = typeof obj === 'object' ? obj : {}; // Split the path into and array if its not one already let keys = Array.isArray(path) ? path : path.split('.'); let newObj = setNestedKey(obj, keys, value); if (keys.length === 1) { return newObj; } keys.pop(); return assignObject(obj, keys, newObj); } /**********************************************/
Let me show you how to use them
For example, if you have this nested object below :
let myAccounts = [ { name : 'account name 1', contact : [ { firstName : 'first name 1', lastName : 'last name 1' }, { firstName : 'first name 2', lastName : 'last name 2' } ] }, { name : 'account name 2', contact : [ { firstName : 'first name 1', lastName : 'last name 1' }, { firstName : 'first name 2', lastName : 'last name 2' } ] } ];
to change the contact last name 2 of account name 2, you can use the assignObject function like this :
myAccounts = assignObject(myAccounts,'1.contact.1.lastName','new last name');
and you can also add a new contact like this :
myAccounts = assignObject(myAccounts,'1.contact',
{
firstName : 'first name 3',
lastName : 'last name 3'
}
);
I think it is very useful and hope you will like these utility functions!
You can learn more about LWC properties security here :
- https://github.com/salesforce/observable-membrane
- https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.create_components_data_flow
Join us tomorrow for more fun with Texeï’s Advent Calendar! 🎁
Want to learn more about Lightning? So, don’t miss our articles Refresh a record page from a Lightning web component and From Visualforce to Lightning Development.
#Texei #SalesForce #AwesomeDeveloper