Accueil > Conseils > Day 12 : Manage nested Object in your Lightning Web Components

Day 12 : Manage nested Object in your Lightning Web Components

 3 min read

AUTEUR
DATE

décembre 12, 2021

CATEGORIES
HASHTAGS
PARTAGEZ !
ABONNEZ-VOUS :
Ho-ho-ho! Christmas is just around the corner and it is time for another little tip from our Texeï’s Advent Calendar !

What’s new today ?

Wrapper Class gives extra flexibility to Salesforce developers. A wrapper or container class is a a data structure which contains different objects or collection 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, has you know, since winter 20, security for immutable @api properties has been increased for LWC. Each Object’s elements are read-only to prevent the 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 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 very useful and hope you will like these utility functions !

You can learn more about LWC properties security here :

Join us tomorrow for more fun with Texeï’s Advent Calendar 🎁

#Texei #SalesForce #AwesomeDeveloper