3

I am trying to get the value from a data file with nested objects.

I want to create a label for each entry that i have under the EN object. So I would like to end up having a "mail" label a "quote" label and a "phone" label.

In the label I want to put the content of tabLabel and tabIcon by accessing it.

With Object.Keys() i can see the strings but when I try to console.log them I get undefined.

I did this function but is not working:

function generateLabel() {
  const keys = Object.keys(TabFormData.EN);
  for (let i = 0; i < keys; i += 1) {
    return `
      <div class="${ID}_tab-form__headerItemWrap">
        <label for="taLabel-here"><i class="tabIcon-here"></i></label>
      </div>
    `;
  }
}

This is the data:

const TabFormData = {
  EN: {
    mail: [
      {
        tabLabel: 'Email Our Team',
        tabIcon: 'fa fa-envelope',
      },
      {
        label: 'First Name',
        type: 'text',
        name: 'name',
        required: true,
        hint: 'Please, provide your Name.',
      },
      {
        label: 'Last Name',
        type: 'text',
        name: 'surname',
        required: true,
        hint: 'Please, provide your Last Name.',
      },
      {
        label: 'Email Address',
        type: 'email',
        name: 'email',
        required: true,
        hint: 'Please, provide a valid email.',
      },
      {
        label: 'Your Message',
        type: 'textarea',
        required: true,
        name: 'message',
        hint: 'Write us a message.',
        rows: 20,
        cols: 50,
      },
      {
        label: 'About You',
        required: true,
        select: [
          'Home use',
          'Business use',
          'Freelance, professional',
        ],
      },
    ],
    quote: [
      {
        tabLabel: 'Request a Quote',
        tabIcon: 'fa fa-file-invoice-dollar',
      },
      {
        label: 'First Name',
        type: 'text',
        name: 'name',
        required: true,
        hint: 'Please, provide your Name.',
      },
      {
        label: 'Last Name',
        type: 'text',
        name: 'surname',
        required: true,
        hint: 'Please, provide your Last Name.',
      },
      {
        label: 'Phone Number',
        type: 'number',
        name: 'telephone',
        required: true,
        hint: 'Please, provide a valid number',
      },
      {
        label: 'Email Address',
        type: 'email',
        name: 'email',
        required: false,
        hint: 'Please, provide a valid email.',
      },
      {
        label: 'Your Message',
        type: 'textarea',
        required: false,
        name: 'message',
        hint: 'Write us a message.',
        rows: 20,
        cols: 50,
      },
      {
        label: 'About You',
        required: true,
        select: [
          'Home use',
          'Business use',
          'Freelance, professional',
        ],
      },
    ],
    call: [
      {
        tabLabel: 'Call Me Back',
        tabIcon: 'fa fa-phone',
      },
      {
        label: 'First Name',
        type: 'text',
        name: 'name',
        required: true,
        hint: 'Please, provide your Name.',
      },
      {
        label: 'Last Name',
        type: 'text',
        name: 'surname',
        required: true,
        hint: 'Please, provide your Last Name.',
      },
      {
        label: 'Phone Number',
        type: 'number',
        name: 'telephone',
        required: true,
        hint: 'Please, provide a valid number',
      },
      {
        label: 'About You',
        required: true,
        select: [
          'Home use',
          'Business use',
          'Freelance, professional',
        ],
      },
    ],
  },
  IT: {

  },
};
JJJ
  • 32,902
  • 20
  • 89
  • 102
d0t_m
  • 87
  • 7
  • Possible duplicate of [Access / process (nested) objects, arrays or JSON](https://stackoverflow.com/questions/11922383/access-process-nested-objects-arrays-or-json) – str Dec 27 '18 at 12:13

4 Answers4

2

Your problem is in the loop.

for (let i = 0; i < keys; i += 1)

In here you're checking if i is less than an array object, which is not what you want. You want to compare i against the number of items in the array.

So that would become this:

for (let i = 0; i < keys.length; i += 1)

Your string literal is also wrong, ID in this case is an undefined variable. I assume you want the name of the key. For this issue it should become:

<div class="${keys[i]}_tab-form__headerItemWrap">

Also, once you return from the for loop, it'll automatically break on the first iteration (meaning you'll always get only one item). What you could do is build your whole string first then return it.

That would make your function become:

function generateLabel() {
  const keys = Object.keys(TabFormData.EN);
  var str = "";
  for (let i = 0; i < keys.length; i += 1) {
    str +=
      `<div class="${keys[i]}_tab-form__headerItemWrap">
        <label for="taLabel-here"><i class="tabIcon-here"></i></label>
      </div>
    `;
  }

  return str;
}

Here's a Fiddle.

Adrian
  • 8,271
  • 2
  • 26
  • 43
0

As reported by @Adriani6, you have issues in the loop, but to actually answer your question, here's how to access the nested objects:

function generateLabel() {
    const keys = Object.keys(TabFormData.EN);
    for (let i = 0; i < keys.length; i += 1) {
        let currentTabObject = TabFormData.EN[keys[i]];
        console.log(currentTabObject[0].tabLabel);
        console.log(currentTabObject[0].tabIcon);
    }
}
Francesco Abeni
  • 4,190
  • 1
  • 19
  • 30
0

If I understand correctly, you are looking something like this:

let cb = (v) => `<div class="${v[0]}"><label for="${v[1][0]['tabLabel']}"><i class="${v[1][0]['tabIcon']}"></i></label></div>`
Object.entries(TabFormData['EN']).map(cb); 

Object.keys() returns the only the keys of the object, however it seems that you want to access the values as well. So, in your case Object.entries() is preferred.

I recommend to read the link below: https://javascript.info/keys-values-entries

Marios Simou
  • 181
  • 3
  • 8
  • thanks, this is what I was looking for. Also I discovered that I was importing the data in the wrong way. **import TabFormData** instead of **import { TabFormData }**. – d0t_m Dec 28 '18 at 10:37
  • Happy coding!. Please up-vote if that one was your solution – Marios Simou Dec 28 '18 at 10:42
0

Assuming you assign TabFormData.EN to a variable called data and the Object.keys result of TabFormData.EN to a variable called keys, you can use:

  • ${keys[i]} to retrieve the name and append it to your div classname,
  • ${data[keys[i]][0].tabLabel} to retrieve the tabLabel property value and append it to your <label> tag, and
  • ${data[keys[i]][0].tabIcon} to retrieve the tabIcon property value and append it to your <i> tag.

You can ignore the <hr> tags, the <button> tag and the rendered <div> tags and just check the object property references in the code snippet below if you want. They are just there for illustrating the code results in the jsFiddle and the code snippet below:

/* JavaScript */
var x = document.getElementById('abc');
var btn = document.getElementById('btn');

function generateLabel() {
  const data = TabFormData.EN;
  const keys = Object.keys(data);
  
  for (let i = 0; i < keys.length; i += 1) {
    x.innerHTML += `
     <hr>
          <div class="${keys[i]}_tab-form__headerItemWrap">
            <label for="${data[keys[i]][0].tabLabel}">
              <i class="${data[keys[i]][0].tabIcon}-here">
                  class of this div is ${keys[i]}_tab-form__headerItemWrap, label for this is ${data[keys[i]][0].tabLabel} and icon is ${data[keys[i]][0].tabIcon}
              </i>
            </label>
          </div>
        <hr>`
  }
}

btn.addEventListener('click', generateLabel);

const TabFormData = {
  EN: {
    mail: [
      {
        tabLabel: 'Email Our Team',
        tabIcon: 'fa fa-envelope',
      },
      {
        label: 'First Name',
        type: 'text',
        name: 'name',
        required: true,
        hint: 'Please, provide your Name.',
      },
      {
        label: 'Last Name',
        type: 'text',
        name: 'surname',
        required: true,
        hint: 'Please, provide your Last Name.',
      },
      {
        label: 'Email Address',
        type: 'email',
        name: 'email',
        required: true,
        hint: 'Please, provide a valid email.',
      },
      {
        label: 'Your Message',
        type: 'textarea',
        required: true,
        name: 'message',
        hint: 'Write us a message.',
        rows: 20,
        cols: 50,
      },
      {
        label: 'About You',
        required: true,
        select: [
          'Home use',
          'Business use',
          'Freelance, professional',
        ],
      },
    ],
    quote: [
      {
        tabLabel: 'Request a Quote',
        tabIcon: 'fa fa-file-invoice-dollar',
      },
      {
        label: 'First Name',
        type: 'text',
        name: 'name',
        required: true,
        hint: 'Please, provide your Name.',
      },
      {
        label: 'Last Name',
        type: 'text',
        name: 'surname',
        required: true,
        hint: 'Please, provide your Last Name.',
      },
      {
        label: 'Phone Number',
        type: 'number',
        name: 'telephone',
        required: true,
        hint: 'Please, provide a valid number',
      },
      {
        label: 'Email Address',
        type: 'email',
        name: 'email',
        required: false,
        hint: 'Please, provide a valid email.',
      },
      {
        label: 'Your Message',
        type: 'textarea',
        required: false,
        name: 'message',
        hint: 'Write us a message.',
        rows: 20,
        cols: 50,
      },
      {
        label: 'About You',
        required: true,
        select: [
          'Home use',
          'Business use',
          'Freelance, professional',
        ],
      },
    ],
    call: [
      {
        tabLabel: 'Call Me Back',
        tabIcon: 'fa fa-phone',
      },
      {
        label: 'First Name',
        type: 'text',
        name: 'name',
        required: true,
        hint: 'Please, provide your Name.',
      },
      {
        label: 'Last Name',
        type: 'text',
        name: 'surname',
        required: true,
        hint: 'Please, provide your Last Name.',
      },
      {
        label: 'Phone Number',
        type: 'number',
        name: 'telephone',
        required: true,
        hint: 'Please, provide a valid number',
      },
      {
        label: 'About You',
        required: true,
        select: [
          'Home use',
          'Business use',
          'Freelance, professional',
        ],
      },
    ],
  },
  IT: {

  },
};
/* CSS */
<!-- HTML -->

<button id="btn">
Click Me
</button>
<div id="abc"></div>
AndrewL64
  • 15,794
  • 8
  • 47
  • 79