I am trying to create new nested tree object array from existing deeply nested object array, as to build a tree node I want id, name and its nested children's if any.
const treeData = [{
"jssType": "fieldset",
"jssSelectLabel": "Fieldset (with legend)",
"jssSelectGroup": "jssItem",
"jsName": "fieldset-715",
"jssLabel": "Legend",
"jssIcon": "typcn typcn-folder",
"expanded": true,
"children": [{
"jssType": "list-ol",
"jssSelectLabel": "List - ol",
"jssSelectGroup": "jssItem",
"jsName": "list-ol-147",
"jssLabel": "",
"jssIcon": "dashicons dashicons-editor-ol",
"noChildren": false,
"expanded": true,
"children": [{
"jssType": "list-li",
"jssSelectLabel": "List Item - li",
"jssSelectGroup": "jssItem",
"jsName": "list-li-752",
"jssLabel": "",
"jssIcon": "dashicons dashicons-editor-ul",
"noChildren": false,
"expanded": true,
"children": [{
"jssType": "text",
"jssSelectLabel": "Text (short text)",
"jssSelectGroup": "jsTag",
"jsName": "text-422",
"jssLabel": "Your Name (required)",
"jsRequired": true,
"jsTagOptions": [{
"jsOption": "",
"optionLabel": "Default value",
"optionType": "input"
},
{
"jsOption": "placeholder",
"isChecked": false,
"optionLabel": "Use this text as the placeholder of the field",
"optionType": "checkbox"
},
{
"jsOption": "akismet_author_email",
"isChecked": false,
"optionLabel": "Akismet - this field requires author's email address",
"optionType": "checkbox"
}
],
"jsValues": "",
"jsPlaceholder": false,
"jsAkismetAuthor": false,
"jsIdAttribute": "",
"jsClassAttribute": "",
"jssIcon": "typcn typcn-sort-alphabetically",
"noChildren": true
}]
},
{
"jssType": "list-li",
"jssSelectLabel": "List Item - li",
"jssSelectGroup": "jssItem",
"jsName": "list-li-538",
"jssLabel": "",
"jssIcon": "dashicons dashicons-editor-ul",
"noChildren": false,
"expanded": true,
"children": [{
"jssType": "email",
"jssSelectLabel": "Email",
"jssSelectGroup": "jsTag",
"jsName": "email-842",
"jssLabel": "Email Address (required)",
"jsRequired": true,
"jsTagOptions": [{
"jsOption": "",
"optionLabel": "Default value",
"optionType": "input"
},
{
"jsOption": "placeholder",
"isChecked": false,
"optionLabel": "Use this text as the placeholder of the field",
"optionType": "checkbox"
},
{
"jsOption": "akismet_author_email",
"isChecked": false,
"optionLabel": "Akismet - this field requires author's email address",
"optionType": "checkbox"
}
],
"jsValues": "",
"jsPlaceholder": false,
"jsAkismetAuthorEmail": false,
"jsIdAttribute": "",
"jsClassAttribute": "",
"jssIcon": "typcn typcn-mail",
"noChildren": true
}]
},
{
"jssType": "list-li",
"jssSelectLabel": "List Item - li",
"jssSelectGroup": "jssItem",
"jsName": "list-li-855",
"jssLabel": "",
"jssIcon": "dashicons dashicons-editor-ul",
"noChildren": false,
"expanded": true,
"children": [{
"jssType": "textarea",
"jssSelectLabel": "Textarea (long text)",
"jssSelectGroup": "jsTag",
"jsName": "textarea-217",
"jssLabel": "Your Message",
"jsRequired": false,
"jsTagOptions": [{
"jsOption": "",
"optionLabel": "Default value",
"optionType": "input"
},
{
"jsOption": "placeholder",
"isChecked": false,
"optionLabel": "Use this text as the placeholder of the field",
"optionType": "checkbox"
}
],
"jsValues": "",
"jsPlaceholder": false,
"jsIdAttribute": "",
"jsClassAttribute": "",
"jssIcon": "typcn typcn-document-text",
"noChildren": true
}]
}
]
},
{
"jssType": "paragraph",
"jssSelectLabel": "Paragraph - p",
"jssSelectGroup": "jssItem",
"jsName": "paragraph-993",
"jssContent": "* Required",
"jssIcon": "dashicons dashicons-editor-paragraph",
"noChildren": true
}
]
},
{
"jssType": "submit",
"jssSelectLabel": "Submit",
"jssSelectGroup": "jsTag",
"jsName": "submit-704",
"jssLabel": "Send",
"jsValues": "",
"jsRequired": false,
"jsIdAttribute": "",
"jsClassAttribute": "",
"jssIcon": "typcn typcn-mail",
"noChildren": true
},
];
My expected data will be in format like below model:
export class TreeNode {
id: number;
label: string;
level: number;
expandable: boolean;
children: TreeNode[];
sequence?: string;
isParentNode?: boolean;
}
I am able to achieve this using multiple loops but lot of code is repetitive in that case so I am looking for some recursive function. So using minimal cade I will be able to retrieve entire array and prepare new array of object from this. Can any one please help me to achieve this. Thankyou in advance.
Note: Using this newly created data I want to display material nested tree on ui.
CodePudding user response:
sounds like it should be easilly doable through recursion
function treeDataToTree(treeData: any[], level = 0): TreeNode[] {
return treeData.map(item => treeItemToTree(item, level));
}
function treeItemToTree(treeDataItem: any, level = 0): TreeNode {
const treeNode = new TreeNode();
treeNode.id=treeDataItem.id;
// other fields that you need
if(treeDataItem.children) treeNode.children = treeDataToTree(treeDataItem.children, level 1);
return treeNode;
}
CodePudding user response:
considered index as id
, jssSelectLabel as label
, you can replace accordingly. Figureout isParentNode
by Boolean(children.length)
const treeData=[{"jssType":"fieldset","jssSelectLabel":"Fieldset (with legend)","jssSelectGroup":"jssItem","jsName":"fieldset-715","jssLabel":"Legend","jssIcon":"typcn typcn-folder","expanded":true,"children":[{"jssType":"list-ol","jssSelectLabel":"List - ol","jssSelectGroup":"jssItem","jsName":"list-ol-147","jssLabel":"","jssIcon":"dashicons dashicons-editor-ol","noChildren":false,"expanded":true,"children":[{"jssType":"list-li","jssSelectLabel":"List Item - li","jssSelectGroup":"jssItem","jsName":"list-li-752","jssLabel":"","jssIcon":"dashicons dashicons-editor-ul","noChildren":false,"expanded":true,"children":[{"jssType":"text","jssSelectLabel":"Text (short text)","jssSelectGroup":"jsTag","jsName":"text-422","jssLabel":"Your Name (required)","jsRequired":true,"jsTagOptions":[{"jsOption":"","optionLabel":"Default value","optionType":"input"},{"jsOption":"placeholder","isChecked":false,"optionLabel":"Use this text as the placeholder of the field","optionType":"checkbox"},{"jsOption":"akismet_author_email","isChecked":false,"optionLabel":"Akismet - this field requires author's email address","optionType":"checkbox"}],"jsValues":"","jsPlaceholder":false,"jsAkismetAuthor":false,"jsIdAttribute":"","jsClassAttribute":"","jssIcon":"typcn typcn-sort-alphabetically","noChildren":true}]},{"jssType":"list-li","jssSelectLabel":"List Item - li","jssSelectGroup":"jssItem","jsName":"list-li-538","jssLabel":"","jssIcon":"dashicons dashicons-editor-ul","noChildren":false,"expanded":true,"children":[{"jssType":"email","jssSelectLabel":"Email","jssSelectGroup":"jsTag","jsName":"email-842","jssLabel":"Email Address (required)","jsRequired":true,"jsTagOptions":[{"jsOption":"","optionLabel":"Default value","optionType":"input"},{"jsOption":"placeholder","isChecked":false,"optionLabel":"Use this text as the placeholder of the field","optionType":"checkbox"},{"jsOption":"akismet_author_email","isChecked":false,"optionLabel":"Akismet - this field requires author's email address","optionType":"checkbox"}],"jsValues":"","jsPlaceholder":false,"jsAkismetAuthorEmail":false,"jsIdAttribute":"","jsClassAttribute":"","jssIcon":"typcn typcn-mail","noChildren":true}]},{"jssType":"list-li","jssSelectLabel":"List Item - li","jssSelectGroup":"jssItem","jsName":"list-li-855","jssLabel":"","jssIcon":"dashicons dashicons-editor-ul","noChildren":false,"expanded":true,"children":[{"jssType":"textarea","jssSelectLabel":"Textarea (long text)","jssSelectGroup":"jsTag","jsName":"textarea-217","jssLabel":"Your Message","jsRequired":false,"jsTagOptions":[{"jsOption":"","optionLabel":"Default value","optionType":"input"},{"jsOption":"placeholder","isChecked":false,"optionLabel":"Use this text as the placeholder of the field","optionType":"checkbox"}],"jsValues":"","jsPlaceholder":false,"jsIdAttribute":"","jsClassAttribute":"","jssIcon":"typcn typcn-document-text","noChildren":true}]}]},{"jssType":"paragraph","jssSelectLabel":"Paragraph - p","jssSelectGroup":"jssItem","jsName":"paragraph-993","jssContent":"* Required","jssIcon":"dashicons dashicons-editor-paragraph","noChildren":true}]},{"jssType":"submit","jssSelectLabel":"Submit","jssSelectGroup":"jsTag","jsName":"submit-704","jssLabel":"Send","jsValues":"","jsRequired":false,"jsIdAttribute":"","jsClassAttribute":"","jssIcon":"typcn typcn-mail","noChildren":true},];
function nodeMapper(obj, id, level=0){
const { expanded:expandable, jssSelectLabel:label} =obj;
let children = [];
const resp = { id, label, expandable, level };
// if has childern then make recersive call to nodeMapper function for each childern
if(obj.children){
children = obj.children.map((o,i )=> nodeMapper(o,i, level 1));
}
return { ...resp, children, isParentNode: Boolean(children.length) };
}
const result = treeData.map((o, i) => nodeMapper(o, i));
console.log(result);