TransWikia.com

Extracting keys and values from nested Object/Array in Javascript

Stack Overflow Asked by Nitish Kumar on February 23, 2021

I’m working on dynamic form builder where I’ve form elements inside row/column grid structure, each of my form elements (object) have a special key named model which defines the field name and value key which defines its value. I have again have nested form which does the same, I need to extract these model and values and make them an Object in case of form repeater it will be an array. Here’s a sample format of my form data:

[
   {
      "component":"row",
      "attrs":{
         "child_components":[
            {
               "component":"column",
               "attrs":{
                  "child_components":[
                     {
                        "component":"input-text",
                        "attrs":{
                           "child_components":[

                           ],
                           "model":"first_name",
                           "value":"",
                        }
                     },
                     {
                        "component":"input-text",
                        "attrs":{
                           "child_components":[

                           ],
                           "model":"last_name",
                           "value":"",
                        }
                     }
                  ]
               }
            },
            {
               "component":"column",
               "attrs":{
                  "child_components":[
                     {
                        "component":"form-repeater",
                        "attrs":{
                           "child_components":[
                              {
                                 "component":"column",
                                 "attrs":{
                                    "child_components":[
                                       {
                                          "component":"input-text",
                                          "attrs":{
                                             "child_components":[

                                             ],
                                             "model":"name",
                                             "value": ""
                                          }
                                       },
                                       {
                                          "component":"input-text",
                                          "attrs":{
                                             "child_components":[

                                             ],
                                             "model":"url",
                                             "value":""
                                          }
                                       }
                                    ]
                                 }
                              },
                              {
                                 "component":"column",
                                 "attrs":{
                                    "child_components":[
                                       {
                                          "component":"input-text",
                                          "attrs":{
                                             "child_components":[

                                             ],
                                             "model":"name",
                                             "value":""
                                          }
                                       },
                                       {
                                          "component":"input-text",
                                          "attrs":{
                                             "child_components":[

                                             ],
                                             "model":"url",
                                             "value":""
                                          }
                                       }
                                    ]
                                 }
                              }
                           ],
                           "model":"links",
                           "value":""
                        }
                     }
                  ]
               }
            }
         ]
      }
   }
]

To execute this I’m trying to do make a recursive function:

findModel(ele) {
  ele.forEach((element) => {
    if(typeof element.attrs.model !== 'undefined') {
      if(element.component === 'form-repeater') {
        let repeater = [];
        element.attrs.child_components.forEach((rep) => {
          let data = this.findModel(rep.attrs.child_components);
          repeater.push(data);
        })
        const repeaterData = {}
        repeaterData[element.attrs.model] = repeater;
        return repeaterData;
      }
      else {
        const data = {}
        data[element.attrs.model] = element.attrs.value;
        return data;
      }
    }
    else {
      if(typeof element.attrs.child_components !== 'undefined' && element.attrs.child_components.length) {
        return this.findModel(element.attrs.child_components);
      }
    }
  })
},

And I’m calling this function:

let data = findModel(form_data)
console.log(data)
//Always comes undefined.

My final format of data will look something like this which I’m unable to achieve:

{
    first_name: '',
    last_name: '',
    links: [
        {name: '', url: ''},
        {name: '', url: ''}
    ]
}

Help me out in achieving the above format. Any better approach to this is most welcome. Thanks.

One Answer

Your function returns undefined because it does not have a return statement. The return statements that you have, are returning from the forEach callback, which is (obviously) not the same function.

Returning a value in a forEach callback is useless, as that value disappears in oblivion. A forEach is not intended for that.

You need to:

  1. use .map instead of .forEach
  2. return the result of .map

So:

return ele.map((element) => {

Finally, there is a case in your callback logic where you do not return a value: the outer else block has a return inside an if block, but there is no return statement for when that inner if condition is not true. So there is a theoretical possibility that the callback will return undefined in some cases, meaning that the .map will return an array with a potential undefined element.

You should make sure that all cases, within the callback code, result in a controlled return.

Answered by trincot on February 23, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP