Scanning an array js object - javascript

Hello, I want to make a basic visual editor for my plugins.
let x = {
tag : "a",
atts : {
href : "/",
class : "a",
text:"link"
},
components:[
{
tag : "b",
atts : {
class : "a",
text:"asdsad"
},
components:[
//...
]
}
]
}
I have an js object like this. I want to get all "components" properties in this.
function render_blocks(blocks){
for (let i = 0; i < blocks.length; i++) {
const block = blocks[i];
let $block_html = $("<"+ block.tag +">",{...block.atts});
if(block.components){
for (let k = 0; k < block.components.length; k++) {
const block_comp = block.components[k];
let $block_html_comp = $("<"+ block_comp.tag +">",{...block_comp.atts});
$block_html.html($block_html.html()+$block_html_comp[0].outerHTML);
}
}
html = $block_html[0].outerHTML;
console.log(html);
}
}
I am using a this function to convert js blocks to html. However this func is very bad :P.
Please HELLLP...
-Edit:
How can I scan nested components properties in my object? They may be a lot of. I am searching a efficient way.

You can use recursion
let x = {
tag: "a",
atts: {
href: "/",
class: "a",
text: "link"
},
components: [
{
tag: "b",
atts: {
class: "a",
text: "asdsad"
},
components: [{ last: "last" }]
}
]
};
let componentsArray = [];
function getComponents(obj) {
if (!obj.components) {
return;
}
componentsArray.push(obj.components);
obj.components.forEach(component => getComponents(component));
}
getComponents(x);
console.log("componentsArray ", componentsArray);

I solved my problem myself.
Answer
// sample blocks
let x = {
tag: "a",
atts: {
href: "/",
class: "a"
},
components: [{
tag: "b",
atts: {
class: "a",
text: "asdsad"
},
components: [{
tag: "b",
atts: {
class: "a",
text: "asdsad"
},
components: [
//...
]
}]
}]
}
function Block(block) {
this.components = []
if (block.components) {
this.components = block.components;
}
this.block = block;
}
Block.prototype.get_components = function() {
return (this.components ? (this.components.length <= 0 ? false : this.components) : false);
}
Block.prototype.find_inner_components = function() {
let has_components = this.get_components();
let parent_components_arr = [];
let section_components_arr = [];
while (has_components) {
let cur_components = has_components;
has_components = false;
for (let i = 0; i < cur_components.length; i++) {
let new_block = new Block(cur_components[i]);
section_components_arr.push(new_block);
has_components = has_components || new_block.get_components();
}
parent_components_arr.push(section_components_arr);
section_components_arr = [];
}
return parent_components_arr;
}
let a = new Block(x);
console.log(a.find_inner_components())

Related

I got error in react while using normal javascript

i am working on react-flow, and my task is to transform the following data => `
`const configObj = {
name: "Dataset",
nodeChild: {
type: "schema",
nodeConfiguration: {
sid1: {
name: "Schema 1",
nodeChild: {
type: "dashboard",
nodeConfiguration: {
did1: {
name: "Dashboard 1"
}
}
}
},
sid2: {
name: "Schema 2",
nodeChild: {
type: "dashboard",
nodeConfiguration: {
did2: {
name: "Dashboard s1",
},
did3: {
name: "Dashboard 3"
}
}
}
}
}
}
}` to this ->
const elements = [
{
id: '1',
type: 'input', // input node
data: { label: 'Input Node' },
position: { x: 250, y: 25 },
},
// default node
{
id: '2',
// you can also pass a React component as a label
data: { label: <div>Default Node</div> },
position: { x: 100, y: 125 },
},
{
id: '3',
type: 'output', // output node
data: { label: 'Output Node' },
position: { x: 250, y: 250 },
},
// animated edge
{ id: 'e1-2', source: '1', target: '2', animated: true },
{ id: 'e2-3', source: '2', target: '3' },
];
`
not exactly but according to data1 so i prepare a code for it and it is working well in node environment but the moment i try it on react it shows some errorenter image description here here is my code
const configObj = {
name: "Dataset",
onClick: true,
nodeChild: {
type: "schema",
nodeConfiguration: {
sid1: {
name: "Schema 1",
nodeChild: {
type: "dashboard",
nodeConfiguration: {
did1: {
name: "Dashboard 1"
}
}
}
},
sid2: {
name: "Schema 2",
nodeChild: {
type: "dashboard",
nodeConfiguration: {
did2: {
name: "Dashboard s1",
nodeChild: {
type: "ritik",
nodeConfiguration: {
ri1: {
name: "Ritik",
}
}
}
},
did3: {
name: "Dashboard 3"
}
}
}
}
}
},
}
let count =1;
let dataConfig = []
const recursion = (obj, level,type) => {
let objData = {}
for(let j in obj){
if(j !== 'nodeChild' && j !== 'nodeParent'){
if(j === 'name'){
objData= {
...objData,
label: obj[j]
}
}else {
objData= {
...objData,
[j]: obj[j]
}
}
}
}
let idd = count
dataConfig = [...dataConfig, {id: count, data: objData, type, level, parentID}]
count++;
if('nodeChild' in obj){
const {nodeConfiguration, type} = obj.nodeChild
for(let val in nodeConfiguration){
recursion(nodeConfiguration[val], level+1, type, parentID = idd)
}
}
if('nodeParent' in obj){
const {nodeConfiguration, type} = obj.nodeParent
for(let val in nodeConfiguration){
recursion(nodeConfiguration[val], level-1, type)
}
}
}
recursion(configObj, level=0, type='root', parentID=1)
let edges = []
for(let i=1; i<dataConfig.length; i++){
let e = {
id: `e${dataConfig[i].id}-${dataConfig[i].parentID}`,
source: `${dataConfig[i].parentID}`, target: `${dataConfig[i].id}`, animated: true
}
edges = [
...edges,
e
]
}
let finalDataSet = []
let x=650, y=25;
let flag = false;
for(let i in dataConfig){
let element = {}
for(let key in dataConfig[i]){
if(key !== 'parentID'){
if(key === 'type'){
let k = dataConfig[i][key]
if(k === 'schema' || k === 'root'){
element = {
...element,
[key]: 'input'
}
}else {
element = {
...element,
[key]: 'output'
}
}
}else {
element = {
...element,
[key]: dataConfig[i][key]
}
}
}
}
element = {
...element,
position: { x, y }
}
// console.log(i)
finalDataSet = [
...finalDataSet,
element
]
y += 75;
if(!flag){
x = 25;
}
x = flag ? x+155 : x
flag = true
}
for(let i =0; i<edges.length; i++){
finalDataSet = [
...finalDataSet,
edges[i]
]
}
const DataSET = finalDataSet
export default DataSET
this code is perfectly working on local nodejs but the same code pops errors on react.js can any one help me on this
It's the recursion(configObj, level=0, type='root', parentID=1) calls that are causing trouble. You think that level=0 is saying to pass 0 to the level parameter but javascript doesn't recognize that syntax. It thinks that level is some variable you forgot to define. Hence the is not defined error.
To fix the issue, just do something like recursion(configObj, 0, 'root', 1) instead.

Filter children in nested object

I have an object which I'm trying to filter out elements with a path and map, but I can't get past the first level into the nested children.
My object (with UI components removed):
const items = [
{
path: "/login"
},
{
path: "/help"
},
{
name: "Guidelines",
children: [
{
name: "Section 1",
children: [
{
name: "Chapter 1",
path: "/section-1/chapter-1"
},
{
name: "Chapter 2",
path: "/section-1/chapter-2"
}
]
},
{
name: "Section 2",
children: [
{
name: "Chapter 3",
path: "/section-2/chapter-3"
},
{
name: "Chapter 4",
path: "/section-2/chapter-4"
}
]
}
]
}
];
This filters the elements with a path, but only to the first level:
const filteredRoutes = items.filter((route) => route.path);
Result:
[
{"path":"/login"},
{"path":"/help"}
]
My goal is to have a list of routes with 6 items in this Codesandbox
[
{ "path": "/login" },
{ "path": "/help" },
{ "path": "/section-1/chapter-1" },
{ "path": "/section-1/chapter-2" },
{ "path": "/section-2/chapter-3" },
{ "path": "/section-2/chapter-4" },
]
Thanks
const getPath = (x) => (x.path ? { path: x.path } : x.children?.map(getPath));
const filteredRoutes = items && items.map(getPath).flat(Infinity);
Does this solve your problem?
const filteredRoutes = [];
const arr = items.map((item) => {
if (item.path) {
filteredRoutes.push({"path" : item.path});
} else {
item.children.map((child) => {
if (child.children) {
child.children.map((_child) => {
filteredRoutes.push({"path" : _child.path});
})
}
})
}
});
console.log(filteredRoutes);
Would something like this work?
const findRoutesWithPaths = (routes) => {
if (!routes) {
return [];
}
const filteredRoutes = [];
// Loop over all the routes
routes.forEach((item) => {
// Add `path` from self
if (item.path) {
filteredRoutes.push(item);
}
// Add `path`s from children
if (item.children) {
filteredRoutes.push(...findRoutesWithPaths(item.children));
}
});
return filteredRoutes;
};
const filteredRoutes = findRoutesWithPaths(items);
codesandbox
Although you wanted to use the filter method, I found a way to iterate your array of objects recursively in case you have an unknown depth, your pathArray should have a length of 6 given the example data, but it will work of you have more children in your data as well.
var pathArray = [];
//Loop through all the objects in your items array
for (var k = 0; k < items.length; k++) {
//For each object let's gather all the paths in the object
var route = items[k];
function getPath(obj) {
//If the object has a "children" attribute then we should look inside
if (obj.hasOwnProperty("children")) {
for (var i = 0; i < obj.children.length; i++) {
getPath(obj.children[i]);
}
}
// If not then this is the base level, which means there is a path attribute we need to grab
else {
pathArray.push(obj.path); //Add the path to our array
}
}
getPath(route);
}
Let me know if you need any more clarification

With an identifier traverse through a JSON object and get a specific value with the identifier

Traverse through a JSON object which has nested arrays objects inside it .
The label value is provided which is the identifier with which need to return the associated level metrics value . If the label is found in the 2nd level find the metrics at the second level and it should be returned
I couldn't get the logic on how to traverse through an object and return the specific value
function getMetrics(arr, label) {
for (let i = 0; i < arr.length; i++) {
if (arr[i].label === label) {
return arr[i].metricsValue;
} else if (arr[i].children) {
return getMetrics(arr[i].children, label);
}
}
return "Not found";
}
const selectedMetrics = getMetrics(dataObj.series, '1');
Consider the JSON object with children specifies the sub level of the current level .
const dataObj = {
series: [
{
label: "A",
metricsValue: "ma",
children: [
{
label: "A-B",
value: 6,
metricsValue: "ma-mb"
},
{
label: "A-B-C",
metricsValue: "ma-mb-mc",
children: [
{
label : "A-B-C-D",
value: 6,
metricsValue: "ma-mb-mc-md"
}
]
}
]
},
{
label: "1",
metricsValue: "m1",
}
]
};
Expected Result :
When the input is "1", it should return
selectedMetrics= "m1"
Input : "A-B-C-D"
selectedMetrics= "ma-mb-mc-md"
You can perform a Depth first search (DFS) or Breadth first search (BFS) to find metricValues at any level.
Here I'm using DFS to find the required value. This works for data with any nested levels.
const dataObj = { series: [ { label: "A", metricsValue: "ma", children: [ { label: "A-B", value: 6, metricsValue: "ma-mb" }, { label: "A-B-C", metricsValue: "ma-mb-mc", children: [ { label: "A-B-C-D", value: 6, metricsValue: "ma-mb-mc-md" } ] } ] }, { label: "1", metricsValue: "m1"} ] };
function getMetrics(arr, label) {
var result;
for (let i = 0; i < arr.length; i++) {
if (arr[i].label === label) {
return arr[i].metricsValue;
} else if (arr[i].children) {
result = getMetrics(arr[i].children, label);
if (result) {
return result;
}
}
}
return null;
}
console.log("selectedMetrics for 'A' = " + getMetrics(dataObj.series, 'A'));
console.log("selectedMetrics for 'A-B' = " + getMetrics(dataObj.series, 'A-B'));
console.log("selectedMetrics for 'A-B-C' = " + getMetrics(dataObj.series, 'A-B-C'));
console.log("selectedMetrics for 'A-B-C-D' = " + getMetrics(dataObj.series, 'A-B-C-D'));
console.log("selectedMetrics for '1' = " + getMetrics(dataObj.series, '1'));
Your'e passing in the value, so use it instead of the string & you're not accessing the children nodes.
for(var i=0; i< arr.length;i++){
const x = arr[i];
if (x.children.label === value) {
console.log(x.metricValue)
}else{
x.forEach(element => {
if (element.children.label === value) {
console.log(element.metricValue)
}else{
element.forEach(secondEl =>{
if (secondEl.children.label === value) {
console.log(secondEl.metricValue)
}
})
}
});
}
}
You can create a more elegant way of iterating around the children nodes but that may help you out

how to array list to tree in javascript?

I have a list:
var list = ['parent-element', 'child-of-previus-element-1', 'child-of-previus-element-2'];
where each next element in the array is a child of the previous.
I want to transform this list into a tree structure, e.g.:
{
"parent-element": {
"childrens": [{
"child-of-previus-element-1": {
"childrens": [{
"child-of-previus-element-2": {
"childrens": []
}
}]
}
}]
}
}
I have tried:
var list = ['parent-element', 'child-of-previus-element-1', 'child-of-previus-element-2'];
var tree = {};
for (var i = 0; i < list.length; i++) {
if( list[i-1] && tree[list[i-1]] ){
tree[list[i-1]].childrens[list[i]] = {"childrens": []};
} else {
tree[list[i]] = {
"childrens": []
};
}
}
console.log( JSON.stringify(tree) );
but the output is:
{
"parent-element":{
"childrens":[]
},
"child-of-previus-element-2":{
"childrens":[]
}
}
You might reduce it right:
var list = ['parent-element', 'child-of-previus-element-1', 'child-of-previus-element-2'];
var tree = list.reduceRight((child, key) => ({ [key]: { children: [child] } }), null);
console.log(JSON.stringify(tree))

Create a json array dynamically

I have an array of objects like this below,
var A = [
{
"111": ["A", "B", "C"]
},
{
"222": ["D", "E", "F"]
}
];
I would like to create a new array dynamically in the format as shown below using js or jQuery.
key in array A should be mapping to attribute text of AA and value should be to children as given below
var AA = [
{
"text": "111",
"state": "open",
"children": [
{
"text": "A"
},
{
"text": "B"
},
{
"text": "C"
}]
},
{
"text": "222",
"state": "open",
"children": [
{
"text": "D"
},
{
"text": "E"
},
{
"text": "F"
}]
}];
How can I accomplish this ? Any thoughts would be helpful
Thanks for all of your suggestions and help.
But Right now I would like to change variable A and input in the format below,
how can i accomplish the same as before.
var A = {"1":["1_1","1_2","1_3"],
"2":["2_1","2_2"],
"3":["3_1"],
"4":["4_1"],
"5":["5_1","5_2"]};
You can map A to AA using Array.prototype.map() (twice).
var AA = A.map(function(item) {
var key = Object.keys(item)[0]; // this will be reliable only because each item has one property.
return {
'text': key,
'state': 'open',
'children': item[key].map(function(child) {
return { 'text': child };
})
};
});
fiddle
My answer is too long, but its still understandable
var A = [
{"111":["A","B","C"]},
{"222":["D","E","F"]}
];
console.log(A);
A = superGenerator(A);
console.log(A);
function superGenerator(data){
var dataF = [];
var children = [];
for (var i = data.length - 1; i >= 0; i--) {
children[i] = [];
for (var [key, val] of iterate_object(data[i])) {
for (var j = val.length - 1; j >= 0; j--) {
children[i][j] = [];
children[i][j] = {
text : val[j]
}
};
}
dataF[i] = {
text : Object.keys(data[i])[0],
state : 'open',
children : children[i]
}
};
return dataF;
}
function* iterate_object(o) {
var keys = Object.keys(o);
for (var i=0; i<keys.length; i++) {
yield [keys[i], o[keys[i]]];
}
}
You can try it by click Run,
Cheers
Try this :
var A = [
{
"111": ["A", "B", "C"]
},
{
"222": ["D", "E", "F"]
}
];
var AA = A.map(item => {
return {
"text": Object.keys(item)[0],
"state": "open",
"children": item[Object.keys(item)[0]].map(elem => { return {"text": elem} })
}
});
console.log(AA);
You can use array#map to iterate through your array, for each object, iterate all its keys and generate the corresponding object.
var arr = [ { "111": ["A", "B", "C"] }, { "222": ["D", "E", "F"] } ],
result = arr.map(o => Object.keys(o).reduce((r,k) => {
return {
text : k,
state : 'open',
children : o[k].map(text => ({text}))
};
},{}));
console.log(result);

Categories