Home > Back-end >  Is it possible to update specific value of nested object with lodash?
Is it possible to update specific value of nested object with lodash?

Time:07-16

I have a nested object like this

let obj = {
  id: "XXX",
  children: [
    {
      id: "YYY",
      children: [],
      path: ["XXX", "YYY"],
      type: "text"
    },
    {
      id: "ZZZ",
      children: [],
      path: ["XXX", "ZZZ"],
      type: "button"
    }
  ],
  path: ["XXX"],
  type: "row"
};

I need to loop through all the children and update the path by appending an array of strings which is is const newPath = ["A", "B", "C"];

let newObj = cloneDeepWith(obj, (node) => {
  if (node.id) {
    node = { ...node, path: [...newPath, ...node.path] };
    console.log("updated : ", node)
  }
});

So final output of update object should be this

let obj = {
  id: "XXX",
  children: [
    {
      id: "YYY",
      children: [],
      path: ["A", "B", "C", "XXX", "YYY"],
      type: "text"
    },
    {
      id: "ZZZ",
      children: [],
      path: ["A", "B", "C", "XXX", "ZZZ"],
      type: "button"
    }
  ],
  path: ["A", "B", "C", "XXX"],
  type: "row"
};

I'm trying to do it with cloneDeepWith function in lodash like this

let updatedObj = cloneDeepWith(obj, (node) => {
  if (node.id) {
    node = { ...node, path: [...newPath, ...node.path] };
    console.log("updated : ", node)
  }
});

In every console.log it prints the corrected updated node (in this case 3 with parent node) , but it doesn't return in updatedObj

How can I achieve this ?

CodePudding user response:

I'm not sure how to do this is lodash, but doing in plain JS is pretty easy. Your recursion tag is the key..

eg.

let obj = {
  id: "XXX",
  children: [
    {
      id: "YYY",
      children: [],
      path: ["XXX", "YYY"],
      type: "text"
    },
    {
      id: "ZZZ",
      children: [],
      path: ["XXX", "ZZZ"],
      type: "button"
    }
  ],
  path: ["XXX"],
  type: "row"
};

function addABC(obj) {
  if (obj.path) obj.path = ['A','B','C',...obj.path];
  if (obj.children) for (const s of obj.children) addABC(s);
}

addABC(obj);

console.log(obj);

CodePudding user response:

You could do this with Lodash using cloneDeepWith method but in this case it will also modify original data.

let obj = {
  id: "XXX",
  children: [{
      id: "YYY",
      children: [],
      path: ["XXX", "YYY"],
      type: "text"
    },
    {
      id: "ZZZ",
      children: [],
      path: ["XXX", "ZZZ"],
      type: "button"
    }
  ],
  path: ["XXX"],
  type: "row"
};

const newPath = ["A", "B", "C"];

const clone = _.cloneDeepWith(obj, value => {
  if (_.isArray(value.path)) {
    value.path = [...newPath, ...value.path]
  }
})

console.log(clone)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

  • Related