Related
I have a this type of a json object.
{
"id": "001",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001"],
"children": [
{
"id": "002",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "002"],
"children": []
},
{
"id": "003",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "003"],
"children": [
{
"id": "00001",
"type": "B",
"children": []
}
]
},
{
"id": "004",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "004"],
"children": [
{
"id": "005",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "004", "005"],
"children": []
},{
"id": "005",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "004", "005"],
"children": [
{
"id": "00002",
"type": "B",
"children": []
}
]
}
]
},
{
"id": "00003",
"type": "B",
"children": []
}
]
}
I need to replace all the object which is type: "B" , with this (which is mentioned below) type of object which I can get from an object with ids as keys of typed B. This typed B objects can be nested anywhere either as a first child or fifth child of a nested arrays of children
{
"id": "002",
"type": "A",
"value": "aaaaa",
"data:": {},
"children": []
},
How can I do that? This can be deeply nested and there's no specific place where we should replace the objects, beforehand. So, I need to go through the entire object and do that. How should I get it done?
EDIT
I updated the code in the question slightly. There's a path property of the nested in each object, except for typed B objects. So, when replacing the typed B properties with the other object, I need to add the paths in there as well.
eg: path for id: "00001", typed B object should be : ["001", "003", "00001"]
EDIT :
Expected result
{
"id": "001",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001"],
"children": [
{
"id": "002",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "002"],
"children": []
},
{
"id": "003",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "003"],
"children": [
{
"id": "002",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "003", "002"],
"children": []
},
]
},
{
"id": "004",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "004"],
"children": [
{
"id": "005",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "004", "005"],
"children": []
},{
"id": "005",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "004", "005"],
"children": [
{
"id": "002",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "004", "005", "002"],
"children": []
}
]
}
]
},
{
"id": "002",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "002"],
"children": []
}
]
}
lodash if you don't mind.
Use cloneDeepWith to clone the entire tree and replace a specific value.
const data = {"id":"001","type":"A","value":"aaaaa","data:":{},"children":[{"id":"002","type":"A","value":"aaaaa","data:":{},"children":[]},{"id":"003","type":"A","value":"aaaaa","data:":{},"children":[{"id":"00001","type":"B","children":[]}]},{"id":"004","type":"A","value":"aaaaa","data:":{},"children":[{"id":"005","type":"A","value":"aaaaa","data:":{},"children":[]},{"id":"005","type":"A","value":"aaaaa","data:":{},"children":[{"id":"00002","type":"B","children":[]}]}]},{"id":"00003","type":"B","children":[]}]};
const result = _.cloneDeepWith(data, (value) => {
const newObj = {"id": "002", "type": "A", "value": "---NEW VALUE FOR 'B' TYPE---", "data:": {} };
return (value.type === 'B') ? { ...value, ...newObj} : _.noop();
});
console.dir(result, { depth: null } );
.as-console-wrapper{min-height: 100%!important; top: 0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.js" integrity="sha512-2iwCHjuj+PmdCyvb88rMOch0UcKQxVHi/gsAml1fN3eg82IDaO/cdzzeXX4iF2VzIIes7pODE1/G0ts3QBwslA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
--- Update 2--- (Without lodash)
Use local variable to store and combine current path.
const data = { "id": "001", "type": "A", "value": "aaaaa", "data:": {}, "path": ["001"], "children": [{ "id": "002", "type": "A", "value": "aaaaa", "data:": {}, "path": ["001", "002"], "children": [] }, { "id": "003", "type": "A", "value": "aaaaa", "data:": {}, "path": ["001", "003"], "children": [{ "id": "00001", "type": "B", "children": [] }] }, { "id": "004", "type": "A", "value": "aaaaa", "data:": {}, "path": ["001", "004"], "children": [{ "id": "005", "type": "A", "value": "aaaaa", "data:": {}, "path": ["001", "004", "005"], "children": [] }, { "id": "005", "type": "A", "value": "aaaaa", "data:": {}, "path": ["001", "004", "005"], "children": [{ "id": "00002", "type": "B", "children": [] }] }] }, { "id": "00003", "type": "B", "children": [] }] }
const deepReplace = (obj, prevPath = []) => {
if (obj.type === 'A') {
if (obj.children.length) {
obj.children = obj.children.map((childObj) => deepReplace(childObj, obj.path))
}
return obj;
};
if (obj.type === 'B') {
const id = '002';
return { id, type: "A", value: "aaaaa", path: [...prevPath, id], data: {}, children: []};
};
};
console.dir(deepReplace(data), { depth: null });
.as-console-wrapper{min-height: 100%!important; top: 0}
This looks like a tree traversal problem. Here's a way to handle that with depth-first search without recursion.
As mentioned in this answer, recursion should be avoided whenever possible, as it requires more memory and is more difficult to debug than an iterative implementation.
Updated per adjustment in question
const data = {"id":"001","type":"A","value":"aaaaa","data:":{},"path":["001"],"children":[{"id":"002","type":"A","value":"aaaaa","data:":{},"path":["001","002"],"children":[]},{"id":"003","type":"A","value":"aaaaa","data:":{},"path":["001","003"],"children":[{"id":"00001","type":"B","children":[]}]},{"id":"004","type":"A","value":"aaaaa","data:":{},"path":["001","004"],"children":[{"id":"005","type":"A","value":"aaaaa","data:":{},"path":["001","004","005"],"children":[]},{"id":"005","type":"A","value":"aaaaa","data:":{},"path":["001","004","005"],"children":[{"id":"00002","type":"B","children":[]}]}]},{"id":"00003","type":"B","children":[]}]};
const dfs = () => {
const stack = [[data, null]];
while(stack.length) {
const [curr, parent] = stack.pop();
// check for match on type
if (curr.type === "B") {
curr.type = "A";
curr.id = "002";
curr.value = "aaaaa";
curr.data = {};
curr.path = [...parent?.path.slice() ?? [], "002"];
}
curr.children.forEach(child => stack.push([child, curr]));
}
};
dfs();
const output = document.getElementById("output");
output.innerText = JSON.stringify(data, null, 2);
<pre id="output" />
I played around with this in the console and it did what you wanted (based on the json array provided, setting all the "B" to "A" types). It's a recursive function so on any nested child it meets in the "children" array it would call the function again on each item in the array.
function fixObjects (obj) {
if (obj["type"] === "B") {
obj["type"] = "A";
obj["id"] = "002";
obj["value"] = "aaaaa";
obj["data"] = {};
}
if (obj["children"].length > 0) {
obj["children"].forEach (child => fixObjects (child));
}
}
fixObjects (_yourArray)
I have the following array of objects with nested elements in the children property. I need to get objects by their id if the id matches.
[
{
"id": 10,
"name": "Scenarios",
"value": null,
"children": [
{
"id": 12,
"name": "Scenario status",
"value": null,
"children": []
}
]
},
{
"id": 11,
"name": "Forecast source",
"value": null,
"children": []
},
{
"id": 16787217,
"name": "Item#Cust",
"value": null,
"children": [
{
"id": 16787230,
"name": "Customer",
"value": null,
"children": [
{
"id": 16787265,
"name": "Site",
"value": null,
"children": []
},
{
"id": 16787291,
"name": "Commercial Network",
"value": null,
"children": []
},
{
"id": 16787296,
"name": "Distribution Site",
"value": null,
"children": []
}
]
},
{
"id": 16787245,
"name": "Item#Site",
"value": null,
"children": [
{
"id": 16787266,
"name": "Family#Warehouse",
"value": null,
"children": []
}
]
},
{
"id": 16787254,
"name": "Item",
"value": null,
"children": [
{
"id": 16787260,
"name": "Family",
"value": null,
"children": [
{
"id": 16787264,
"name": "Product line",
"value": null,
"children": []
}
]
},
{
"id": 16787261,
"name": "Group 1",
"value": null,
"children": []
}
]
}
]
},
{
"id": 16787267,
"name": "Supplier",
"value": null,
"children": []
},
{
"id": 16787297,
"name": "SKU",
"value": null,
"children": []
}
]
If no match on root element is found, the function should lookup its children to see if there is a match, and the first children match should be pushed on the root level.
For exemple, I have a list of ids: [12, 16787217, 16787245, 16787266]
The function should return only objects where ids matches while keeping hierarchy if matching parent id have matching children id, so it should return this:
[
{
"id": 12,
"name": "Scenario status",
"value": null,
"children": []
},
{
"id": 16787217,
"name": "Item#Cust",
"value": null,
"children": [
{
"id": 16787245,
"name": "Item#Site",
"value": null,
"children": [
{
"id": 16787266,
"name": "Family#Warehouse",
"value": null,
"children": []
}
]
}
]
}
]
As for now, I can get only the first level elements if they are found with this function:
filterArray(array: Array<any>, ids: Array<number>) {
array = array.filter(el => ids.includes(el.id));
for (let i = 0; i < array.length; i++) {
this.filterArray(array[i].children, ids);
}
console.log(array);
}
Anyone have an idea on how to achieve this?
You could reduce the array and take the nodes with found id and children or only the children at the base level.
const
find = (r, { children = [], ...o }) => {
children = children.reduce(find, []);
if (ids.includes(o.id)) r.push({ ...o, children });
else if (children.length) r.push(...children);
return r;
},
data = [{ id: 10, name: "Scenarios", value: null, children: [{ id: 12, name: "Scenario status", value: null, children: [] }] }, { id: 11, name: "Forecast source", value: null, children: [] }, { id: 16787217, name: "Item#Cust", value: null, children: [{ id: 16787230, name: "Customer", value: null, children: [{ id: 16787265, name: "Site", value: null, children: [] }, { id: 16787291, name: "Commercial Network", value: null, children: [] }, { id: 16787296, name: "Distribution Site", value: null, children: [] }] }, { id: 16787245, name: "Item#Site", value: null, children: [{ id: 16787266, name: "Family#Warehouse", value: null, children: [] }] }, { id: 16787254, name: "Item", value: null, children: [{ id: 16787260, name: "Family", value: null, children: [{ id: 16787264, name: "Product line", value: null, children: [] }] }, { id: 16787261, name: "Group 1", value: null, children: [] }] }] }, { id: 16787267, name: "Supplier", value: null, children: [] }, { id: 16787297, name: "SKU", value: null, children: [] }],
ids = [12, 16787217, 16787245, 16787266],
result = data.reduce(find, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could also try this
let data = [
{
"id": 10,
"name": "Scenarios",
"value": null,
"children": [
{
"id": 12,
"name": "Scenario status",
"value": null,
"children": []
}
]
},
{
"id": 11,
"name": "Forecast source",
"value": null,
"children": []
},
{
"id": 16787217,
"name": "Item#Cust",
"value": null,
"children": [
{
"id": 16787230,
"name": "Customer",
"value": null,
"children": [
{
"id": 16787265,
"name": "Site",
"value": null,
"children": []
},
{
"id": 16787291,
"name": "Commercial Network",
"value": null,
"children": []
},
{
"id": 16787296,
"name": "Distribution Site",
"value": null,
"children": []
}
]
},
{
"id": 16787245,
"name": "Item#Site",
"value": null,
"children": [
{
"id": 16787266,
"name": "Family#Warehouse",
"value": null,
"children": []
}
]
},
{
"id": 16787254,
"name": "Item",
"value": null,
"children": [
{
"id": 16787260,
"name": "Family",
"value": null,
"children": [
{
"id": 16787264,
"name": "Product line",
"value": null,
"children": []
}
]
},
{
"id": 16787261,
"name": "Group 1",
"value": null,
"children": []
}
]
}
]
},
{
"id": 16787267,
"name": "Supplier",
"value": null,
"children": []
},
{
"id": 16787297,
"name": "SKU",
"value": null,
"children": []
}
]
let ids = [12, 16787217, 16787245, 16787266]
let filterArray = (mArray, ids) => {
let result = []
for (const x of mArray) {
if (ids.includes(x.id)) {
let element = {...x, children: []}
let childrenFounds = []
if (x.children.length) {
childrenFounds = filterArray(x.children, ids)
if (childrenFounds.length) element.children.push(...childrenFounds)
}else {
delete element.children
}
result.push(element)
} else if (x.children.length) {
let found = filterArray(x.children, ids)
if (found.length) result.push(...found)
}
}
return result
}
let res = filterArray(data, ids)
console.log('res', res)
BE Response:- which I am getting from Backend Service
{
"data": {
"type": "AnyType",
"resources": [
{
"id": 1,
"treeId": "1",
"name": "name1",
"description": "description1",
"children": [
{
"id": 3,
"treeId": "1-3",
"name": "subName1",
"description": "subDescription1",
"children": [
{
"id": 6,
"treeId": "1-3-6",
"name": "subSubName1",
"description": "subSubDesc1",
"children": []
}
]
}
]
},
{
"id": 2,
"treeId": "2",
"name": "name2",
"description": "description2",
"children": [
{
"id": 7,
"treeId": "2-7",
"name": "subName2",
"description": "subDescription2",
"children": []
}
]
}
]
}
}
But I need to modify this response to as below on FE
Expected Response:- means I need to join name and description field text to one(in name field ) as below:-
{
"data": {
"type": "AnyType",
"resources": [
{
"id": 1,
"treeId": "1",
"name": "name1-description1",
"description": "description1",
"children": [
{
"id": 3,
"treeId": "1-3",
"name": "subName1-subDescription1",
"description": "subDescription1",
"children": [
{
"id": 6,
"treeId": "1-3-6",
"name": "subSubName1-subSubDesc1",
"description": "subSubDesc1",
"children": []
}
]
}
]
},
{
"id": 2,
"treeId": "2",
"name": "name2-description2",
"description": "description2",
"children": [
{
"id": 7,
"treeId": "2-7",
"name": "subName2-subDescription2",
"description": "subDescription2",
"children": []
}
]
}
]
}
}
there could be n number of children of each object and children can have an array of objects.
What I have done:- I am able to change the very first name but not children name
let resDataArry = [];
let descData: DynamicResource;
response.forEach((x, index) => {
const descName = x.name + ' ' + x.description;
descData = { ...tree.resources[index], name: descName };
resDataArry.push(descData);
});
return resDataArry;
Please help.
You can use nested Array#forEach to access children array and then concatenate the name and description together.
let data = {
"data": {
"type": "AnyType",
"resources": [
{
"id": 1,
"treeId": "1",
"name": "name1",
"description": "description1",
"children": [
{
"id": 3,
"treeId": "1-3",
"name": "subName1",
"description": "subDescription1",
"children": [
{
"id": 6,
"treeId": "1-3-6",
"name": "subSubName1",
"description": "subSubDesc1",
"children": []
}
]
}
]
},
{
"id": 2,
"treeId": "2",
"name": "name2",
"description": "description2",
"children": [
{
"id": 7,
"treeId": "2-7",
"name": "subName2",
"description": "subDescription2",
"children": []
}
]
}
]
}
}
data.data.resources.forEach(function(item){
item.name = item.name + ' ' + item.description;
item.children.forEach(function(child){
child.name = child.name + ' ' + child.description;
});
});
console.log(data);
Hi I am using JavaScript and jQuery as client side script. I am little bit new to Recursive functions. I have a JSON data as below and I have tried to make a tree structure using below JSON data by writing a recursive function but I am not able to build the tree structure.
var jsonData = { "$id": "45", "_children": [{ "$id": "46", "_children": [{ "$id": "47", "_children": [{ "$id": "48", "_children": [{ "$id": "49", "_children": null, "id": "Test1", "text": "Text1", "name": "name1", "parent": null, "root": { "$ref": "49" }, "depth": 0, "children": [] }], "id": "id1", "text": "text2", "name": "name2", "parent": null, "root": { "$ref": "48" }, "depth": 0, "children": [{ "$ref": "49" }] }], "id": "id3", "text": "text4", "name": "name4", "parent": null, "root": { "$ref": "47" }, "depth": 0, "children": [{ "$ref": "48" }] }, { "$id": "50", "_children": [{ "$id": "51", "_children": [{ "$id": "52", "_children": null, "id": "id6", "text": "text6", "name": "name6", "parent": null, "root": { "$ref": "52" }, "depth": 0, "children": [] }], "id": "id7", "text": "text7", "name": "name7", "parent": null, "root": { "$ref": "51" }, "depth": 0, "children": [{ "$ref": "52" }] }], "id": "id8", "text": "text8", "name": "name8", "parent": null, "root": { "$ref": "50" }, "depth": 0, "children": [{ "$ref": "51" }] }], "id": "id9", "text": "text9", "name": "name9", "parent": null, "root": { "$ref": "46" }, "depth": 0, "children": [{ "$ref": "47" }, { "$ref": "50" }] }, { "$id": "53", "_children": [{ "$id": "54", "_children": null, "id": "id10", "text": "text10", "name": "name10", "parent": null, "root": { "$ref": "54" }, "depth": 0, "children": [] }], "id": "id11", "text": "text11", "name": "name11", "parent": null, "root": { "$ref": "53" }, "depth": 0, "children": [{ "$ref": "54" }] }], "id": "0", "text": "0", "name": "", "parent": null, "root": { "$ref": "45" }, "depth": 0, "children": [{ "$ref": "46" }, { "$ref": "53" }] }
Required Output:
var treeNode = {
id: 101, // random
text: object.name,
icon: "fas fa-plus",
subNode: {
// id, text, icon and subNode of Children object
// recursive data, So on....
}
};
Can anyone suggest me or help me to write javascript or jQuery Recursive function based on above JSON data so I can build tree structure. I know I am asking about help because I do have less knowledge about recursive function.
If we abstract this a bit, it's pretty easy to write a general-purpose tree-mapping function. Then we can supply two callback functions: one to find the child nodes of the input and one to build the output node based on the input and the mapped children. Such a function turns out to be surprisingly simple:
const mapTree = (getChildren, transformNode) => (tree) =>
transformNode (
tree,
(getChildren (tree) || []) .map (mapTree (getChildren, transformNode))
)
For your data, getChildren is simply (node) => node._children
And the node transformation might be as simple as:
const transformNode = (node, children) =>
({
id: node.$id, // or a randomizing call?
text: node.name,
icon: "fas fa-plus", // is this really a fixed value?
subNode: children
})
Putting this together we get
const mapTree = (getChildren, transformNode) => (tree) =>
transformNode (
tree,
(getChildren (tree) || []) .map (mapTree (getChildren, transformNode))
)
const kids = (node) => node._children
const transformNode = (node, children) =>
({
id: node.$id,
text: node.name,
icon: "fas fa-plus",
subNode: children
})
const myTransform = mapTree (kids, transformNode)
const jsonData = { "$id": "45", "_children": [{ "$id": "46", "_children": [{ "$id": "47", "_children": [{ "$id": "48", "_children": [{ "$id": "49", "_children": null, "id": "Test1", "text": "Text1", "name": "name1", "parent": null, "root": { "$ref": "49" }, "depth": 0, "children": [] }], "id": "id1", "text": "text2", "name": "name2", "parent": null, "root": { "$ref": "48" }, "depth": 0, "children": [{ "$ref": "49" }] }], "id": "id3", "text": "text4", "name": "name4", "parent": null, "root": { "$ref": "47" }, "depth": 0, "children": [{ "$ref": "48" }] }, { "$id": "50", "_children": [{ "$id": "51", "_children": [{ "$id": "52", "_children": null, "id": "id6", "text": "text6", "name": "name6", "parent": null, "root": { "$ref": "52" }, "depth": 0, "children": [] }], "id": "id7", "text": "text7", "name": "name7", "parent": null, "root": { "$ref": "51" }, "depth": 0, "children": [{ "$ref": "52" }] }], "id": "id8", "text": "text8", "name": "name8", "parent": null, "root": { "$ref": "50" }, "depth": 0, "children": [{ "$ref": "51" }] }], "id": "id9", "text": "text9", "name": "name9", "parent": null, "root": { "$ref": "46" }, "depth": 0, "children": [{ "$ref": "47" }, { "$ref": "50" }] }, { "$id": "53", "_children": [{ "$id": "54", "_children": null, "id": "id10", "text": "text10", "name": "name10", "parent": null, "root": { "$ref": "54" }, "depth": 0, "children": [] }], "id": "id11", "text": "text11", "name": "name11", "parent": null, "root": { "$ref": "53" }, "depth": 0, "children": [{ "$ref": "54" }] }], "id": "0", "text": "0", "name": "", "parent": null, "root": { "$ref": "45" }, "depth": 0, "children": [{ "$ref": "46" }, { "$ref": "53" }] }
console .log (myTransform (jsonData))
This does something slightly different from your requested output. You had written subNode: { ... }, but instead I'm returning an array of objects, subNodes: [ ... ], as I don't make any real sense of a plain object here.
Also, this will yield an empty subNodes array if an input node has no children. If you would rather not have the subNodes property, you could replace
subNode: children
with something like
...(children .length ? {subNode: children} : {})
Obviously, you don't need the named helpers and could call mapTree with anonymous functions like this:
const myTransform = mapTree (
(node) => node._children,
(node, children) =>
({
id: node.$id,
text: node.name,
icon: "fas fa-plus",
subNode: children
})
)
This mapTree function was very easy to write, as I didn't have to think about any details of the output or input formats as I wrote it. But perhaps that abstraction is not helpful to me, and I'm never going to use it except here. If so, I can simply rework the abstract version by plugging the hard-coded callbacks directly. With only a little manipulation, that will turn it into this version:
const newTransform = (node) =>
({
id: node.$id,
text: node.name,
icon: "fas fa-plus",
subNode: (node._children || []).map(newTransform)
})
const jsonData = { "$id": "45", "_children": [{ "$id": "46", "_children": [{ "$id": "47", "_children": [{ "$id": "48", "_children": [{ "$id": "49", "_children": null, "id": "Test1", "text": "Text1", "name": "name1", "parent": null, "root": { "$ref": "49" }, "depth": 0, "children": [] }], "id": "id1", "text": "text2", "name": "name2", "parent": null, "root": { "$ref": "48" }, "depth": 0, "children": [{ "$ref": "49" }] }], "id": "id3", "text": "text4", "name": "name4", "parent": null, "root": { "$ref": "47" }, "depth": 0, "children": [{ "$ref": "48" }] }, { "$id": "50", "_children": [{ "$id": "51", "_children": [{ "$id": "52", "_children": null, "id": "id6", "text": "text6", "name": "name6", "parent": null, "root": { "$ref": "52" }, "depth": 0, "children": [] }], "id": "id7", "text": "text7", "name": "name7", "parent": null, "root": { "$ref": "51" }, "depth": 0, "children": [{ "$ref": "52" }] }], "id": "id8", "text": "text8", "name": "name8", "parent": null, "root": { "$ref": "50" }, "depth": 0, "children": [{ "$ref": "51" }] }], "id": "id9", "text": "text9", "name": "name9", "parent": null, "root": { "$ref": "46" }, "depth": 0, "children": [{ "$ref": "47" }, { "$ref": "50" }] }, { "$id": "53", "_children": [{ "$id": "54", "_children": null, "id": "id10", "text": "text10", "name": "name10", "parent": null, "root": { "$ref": "54" }, "depth": 0, "children": [] }], "id": "id11", "text": "text11", "name": "name11", "parent": null, "root": { "$ref": "53" }, "depth": 0, "children": [{ "$ref": "54" }] }], "id": "0", "text": "0", "name": "", "parent": null, "root": { "$ref": "45" }, "depth": 0, "children": [{ "$ref": "46" }, { "$ref": "53" }] }
console .log (newTransform (jsonData))
There's an important point here. This generic function was much easier to write than if I'd tried to write something to convert your format directly. While there is a danger in too-early abstraction, it also can offer significant benefits. I might well choose to keep only that last version, but the generic abstraction simplified the development of it.
It can be something like that, with using the json data model
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="lib/style.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<div id="myDiv"></div>
</body>
<script>
var treeData={
"Id":"10",
"text":"Document Categories",
"icon":"fas fa-plus",
"subNode":
[
{
"Id":"11",
"text":"Pdf Documents",
"icon":"fas fa-plus",
"subNode":[
{
"Id":"31",
"text":"Book Pdfs",
"icon":"fas fa-plus",
"subNode":[]
},
{
"Id":"32",
"text":"EPub",
"icon":"fas fa-plus",
"subNode":[
{
"Id":"20",
"text":"EBook Epubs1",
"icon":"fas fa-plus",
"subNode":[]
},
{
"Id":"30",
"text":"EBook Epubs2",
"icon":"fas fa-plus",
"subNode":[]
}
]
}
]
},
{
"Id":"33",
"text":"Text Documents",
"icon":"fas fa-plus",
"subNode":[
{
"Id":"32",
"text":"Book Text",
"icon":"fas fa-plus",
"subNode":[]
},
{
"Id":"35",
"text":"Automatic Text",
"icon":"fas fa-plus",
"subNode":[]
}
]
}
]
};
var newTree = AddRecursive(null, treeData);
var treeDiv = $('#myDiv');
treeDiv.append(newTree);
function AddRecursive(tree, data) {
if (tree == null) {
tree = $('<ul/>');
tree.attr('id', 'treeID');
}
var listU = $('<ul />');
listU.addClass('ul class');
var listItem = $('<li />');
listItem.addClass('li class');
listItem.attr('data-id', data.Id);
var link = $('<a />');
var i = $('<i/>').addClass('fa fa-folder');
link.append(i);
//link.addClass("linkClass");
link.append(data.text);
listItem.append(link);
if (data.subNode.length > 0) {
var span = $(' <span />');
span.addClass('fa-chevron-down');
link.append(span);
}
listU.append(listItem);
tree.append(listU);
for (i in data.subNode) {
AddRecursive(listItem, data.subNode[i]);
}
return tree;
}
</script>
</html>
This is the JSON Object i am working on :
var r={
"id": "A",
"name": "Analysis",
"url": "A.html",
"root": true,
"children": [
{
"id": "B",
"name": "Introduction",
"url": "B.html",
"root": true,
"children": [{
"id": "C",
"name": "Creating",
"url": "c.html#I1"
}, {
"id": "D",
"name": "Running",
"url": "d.html#I2"
}]
},
{
"id": "E",
"name": "Transient Analysis",
"url": "E.html",
"root": true,
"children": [{
"id": "F",
"name": "RC",
"url": "F.html#T1"
}, {
"id": "G",
"name": "RLC",
"url": "G.html#T2"
}]
}
]
}
I want this as another key-value
path="home.html"
and it should be appended not only to the root node but to all its children node.
So it should look like.
var r= {
"id": "A",
"name": "Analysis",
"url": "A.html",
"path":"home.html",
"root": true,
"children": [
{
"id": "B",
"name": "Introduction",
"url": "B.html",
"root": true,
"path":"home.html",
"children": [{
"id": "C",
"name": "Creating",
"url": "c.html#I1",
"path":"home.html"
}, {
"id": "D",
"name": "Running",
"url": "d.html#I2",
"path":"home.html"
}]
},
{
"id": "E",
"name": "Transient Analysis",
"url": "E.html",
"root": true,
"path":"home.html",
"children": [{
"id": "F",
"name": "RC",
"url": "F.html#T1",
"path":"home.html"
}, {
"id": "G",
"name": "RLC",
"url": "G.html#T2",
"path":"home.html"
} ]
}
]
}
so far I've tried is this :
r.path={"home.html"}
and
var to_concatjson = JSON.parse(r);
to_concatjson["path"] = {"home.html"};
but both are not working for me.
Further Modifications in the above question :
Lets say i am loading my json content from my File 1
File 1 looks like
[
{
"id":"a", "name":"a","children":[
{ "id":"b", "name":"b","children":[
{ "id":"b", "name":"b"},
{ "id":"c", "name":"c"},
{ "id":"d", "name":"d"}
]
},
{ "id":"e", "name":"e","children":[
{ "id":"f", "name":"f"},
{ "id":"g", "name":"g"},
{ "id":"h", "name":"h"}
]
},
]
}
]
the content of my json file is loaded in result[0]. and when i am calling addPath like :
result[0]=addPath(result[0]);
it shows me an error that "forEach" will not work as it is not the property of object.
Do it with this code :-
function addPath(obj){
if(!obj.hasOwnProperty('path')){
obj.path = 'home.html';
}
if(obj.hasOwnProperty('children')){
obj.children.forEach(function(obj1){
obj1 = addPath(obj1);
});
}
return obj;
}
r = addPath(r);
I know that my way is not optimum, but it is working:
I append new item through .replace(...) (without loop)
var r = JSON.parse(JSON.stringify(r).replace(new RegExp("\"url\"", 'g'), '"path": "home.html", "url"'));
console.log(r);
var r={
"id": "A",
"name": "Analysis",
"url": "A.html",
"root": true,
"children": [
{
"id": "B",
"name": "Introduction",
"url": "B.html",
"root": true,
"children": [{
"id": "C",
"name": "Creating",
"url": "c.html#I1"
}, {
"id": "D",
"name": "Running",
"url": "d.html#I2"
}]
},
{
"id": "E",
"name": "Transient Analysis",
"url": "E.html",
"root": true,
"children": [{
"id": "F",
"name": "RC",
"url": "F.html#T1"
}, {
"id": "G",
"name": "RLC",
"url": "G.html#T2"
}]
}
]
}
var r = JSON.parse(JSON.stringify(r).replace(new RegExp("\"url\"", 'g'), '"path": "home.html", "url"'));
console.log(r);