Reputation: 5627
I have this small function (within my Angular 7
application) which uses JavaScript reduce()
, and locates an object within a nested array of objects. I can then proceed to update certain properties on the fly.
Now, in addition to this find logic, I would like to also insert/delete
an object into/from the nested array.
Question is: once I do locate my object, can I push() and/or delete an object ?
const input={UID:2,GUID:"",LocationName:"USA",ParentLocation:null,subs:[{UID:42,GUID:"",LocationName:"New Jersey",Description:"",subs:[{UID:3,GUID:"",LocationName:"Essex County",ParentLocation:null,"subs":[{UID:4,LocationName:"Newark",ParentLocation:3,"subs":[{"UID":49,"GUID":"","LocationName":"Doctor Smith's Office","LocationType":{"UID":2,"LocationTypeName":"Practice","Description":"other location"},"subs":[{"HostID":38,"HostName":"Ocean Host",}]}]}]}]}]};
const findUIDObj = (uid, parent) => {
const { UID, subs } = parent;
if (UID === uid) {
const { subs, ...rest } = parent;
return rest;
}
if (subs) return subs.reduce((found, child) => found || findUIDObj(uid, child), null);
};
console.log(findUIDObj(49, input));
var obj = findUIDObj(49, input);
delete obj;
For example, in my Angular 7 app, it complains if I attempt to delete
the found object:
ex/
var obj = findUIDObj(49, input);
delete obj;
'delete' cannot be called on an identifier in strict mode.
Upvotes: 0
Views: 2218
Reputation: 21
Looking briefly at your code, I see you are using a const
identifier to declare your data collection. We only use const
for static data that does not change, and that’s the purpose of it. So, first of all matters, that seems to be the problem. To test it change it to let
. Now, as for methods for data management, immutability is worthy of your consideration for many reasons, but namely Angular will rerender the entire object regardless of altering the existing object, or receiveing a new object. You can look up Immutable JavaScript to understand more. In many cases, creating immutable data management is done with a library, you can do it yourself. Basically, create a function called copy( data )
, or something so that you pass in the original object, but you get a copy of it in return with no reference to the original object. That way one does not accidentally change the original object. To do this you can do this inside of your copy function: return JSON.parse(JSON.stringify( data )) ;
The only problem you might run into here is deep nested objects, or objects with circular references can cause problems. I have an overriding stringify
method to mange this in little libraries I’ve written.
Upvotes: 2
Reputation: 350127
delete obj
would never do what you want: first of all, it is not even an object from your input, since the function created a new object from the found object, excluding the subs
property, and returned that. But more importantly, delete
is used for deleting properties, not objects.
It seems you want to remove a matching object from its parent subs
property. For that you would need to mutate the subs
array, so it would exclude the matching object. For that to work in a generic way, your input should be an array. Otherwise that root object could not be removed from anything.
With that in mind, your lookup function should return the array in which the match was found and at which index. With those pieces of information you can decide to remove that element from the array, or to insert another object at that index.
Here is how it could work with removal:
const input=[{UID:2,GUID:"",LocationName:"USA",ParentLocation:null,subs:[{UID:42,GUID:"",LocationName:"New Jersey",Description:"",subs:[{UID:3,GUID:"",LocationName:"Essex County",ParentLocation:null,"subs":[{UID:4,LocationName:"Newark",ParentLocation:3,"subs":[{"UID":49,"GUID":"","LocationName":"Doctor Smith's Office","LocationType":{"UID":2,"LocationTypeName":"Practice","Description":"other location"},"subs":[{"HostID":38,"HostName":"Ocean Host",}]}]}]}]}]}];
const findUIDObj = (uid, arr) => {
if (!arr) return;
const idx = arr.findIndex(obj => obj.UID === uid);
if (idx > -1) return [arr, idx];
for (const obj of arr) {
const result = findUIDObj(uid, obj.subs);
if (result) return result;
}
};
console.log(findUIDObj(49, input));
const [arr, idx] = findUIDObj(49, input) || [];
if (arr) {
arr.splice(idx, 1); // Remove object from its parent array
}
Upvotes: 1