0

I'm going to create a simple E-commerce application. I have API call, which returns variations object like below. I want to dynamically generate variation boxes. Right now I am receiving one option value, I want to receive options value like image which I have referred to. In addition, the select boxes are dynamic--there can be more than three variations. How can I achieve this result? Thanks in advance.

enter image description here

var variations = [{
        NameValueList: [
            { Name: "Color", Value: ["Cloud White / Core Black"] },
            { Name: "US Shoe Size (Women's)", Value: ["11"] },
        ]
    },
    {
        NameValueList: [
            { Name: "Color", Value: ["Cloud White / Core Green"] },
            { Name: "US Shoe Size (Women's)", Value: ["13"] },
        ]
    },
    {
        NameValueList: [
            { Name: "Color", Value: ["Cloud White / Core White"] },
            { Name: "US Shoe Size (Women's)", Value: ["15"] },
        ]
    },
]


document.getElementById("generateVariations").addEventListener("click", () => {
    var html;
    variations.map(el => {
        html = el.NameValueList.map(nameValue => {
            return `<select name="${nameValue.Name}">
                     <option value="${nameValue.Value[0]}">${nameValue.Value[0]}</option>
                  </select>`
        })
    })

    document.getElementById("variations2").innerHTML = html.join('')

})
<div id="variations2"></div>
<button id="generateVariations">Generate variations</button>

4
  • So from the given code sample that you gave, on the variations variable, each object inside the NameValueList should have a select tag? and are the Values property represent the the number of options? Commented Apr 12, 2021 at 18:08
  • No, in this example my aim is to generate 2 select boxes, first which holds all Color options and the second which holds all Value options Commented Apr 12, 2021 at 18:12
  • so if we were to implement your example, you would expect 2 select boxes with 3 options on each select boxes which has all the same values right? Commented Apr 12, 2021 at 18:15
  • yes you are right, values would be Color("Cloud White / Core Black", "Cloud White / Core Green", "Cloud White / Core White") and US Shoe Size ("11", "13", "15") Commented Apr 12, 2021 at 18:27

2 Answers 2

1

Thanks for answering my questions, this is the solution that I can propose.

First, we need to reconstruct the array of objects on variations using reduce() function, so we can loop easily on the next step. We can also use 1 loop for this but it will be messy, so I thought of we need to do it separately for at least it'll make less mess.

So we want to reconstruct it to this:

[
  "Color": ["Cloud White / Core Black", "Cloud White / Core Black", "Cloud White / Core Black"].
  "US Shoe Size (Women's)": ["11", "13", "15"]
]

Then now we can loop the newly reconstructed array of objects and convert it to a string using .join('') method, and render it on a div element.

var variations = [{
        NameValueList: [
            { Name: "Color", Value: ["Cloud White / Core Black"] },
            { Name: "US Shoe Size (Women's)", Value: ["11"] },
        ]
    },
    {
        NameValueList: [
            { Name: "Color", Value: ["Cloud White / Core Green"] },
            { Name: "US Shoe Size (Women's)", Value: ["13"] },
        ]
    },
    {
        NameValueList: [
            { Name: "Color", Value: ["Cloud White / Core White"] },
            { Name: "US Shoe Size (Women's)", Value: ["15"] },
        ]
    },
]


document.getElementById("generateVariations").addEventListener("click", () => {
    // Reconstruct array of object to easier manage rendering of elements
    const new_variations = variations.reduce((a, b) => {
      // If property already exist in variable "a", push values, else, create one
      b.NameValueList.forEach(obj => {
        let found_variant
        // Finds an existing object based on the 'name' property and initialize it on the 'found_variant' variable
        if (found_variant = a.find(e => e.name === obj.Name)) {
          found_variant.options.push(obj.Value[0]);
        } else {
          a.push({ name: obj.Name, options: [obj.Value[0]] });
        }
      })
      
      return a
    }, [])
    // Loop using the new reconstructed array of objects to render
    const html = new_variations.map(obj => (`
      <label>${obj.name}</label>
      <select name="${obj.name}">
        ${obj.options.map(option => `<option value="${option}">${option}</option>`).join('')}
      </select>
    `)).join('')

    document.getElementById("variations2").innerHTML = html

})
<div id="variations2"></div>
<button id="generateVariations">Generate variations</button>

Sign up to request clarification or add additional context in comments.

Comments

1

Sorry, but the structure for storing your data doesn't seem to be optimal. But if it's given (you cannot change it), then that's that :)

var variations = [{
    NameValueList: [{
        Name: "Color",
        Value: ["Cloud White / Core Black"]
      },
      {
        Name: "US Shoe Size (Women's)",
        Value: ["11"]
      },
    ]
  },
  {
    NameValueList: [{
        Name: "Color",
        Value: ["Cloud White / Core Green"]
      },
      {
        Name: "US Shoe Size (Women's)",
        Value: ["13"]
      },
    ]
  },
  {
    NameValueList: [{
        Name: "Color",
        Value: ["Cloud White / Core White"]
      },
      {
        Name: "US Shoe Size (Women's)",
        Value: ["15"]
      },
    ]
  },
]

const selectObjects = (variations) => {
  return variations.reduce((a, {
    NameValueList: c
  }) => {
    c.forEach(({
      Name,
      Value
    }) => {
      if (typeof a[Name] === "undefined") a[Name] = []
      a[Name] = [...a[Name], ...Value]
    })
    return a
  }, {})
}

const selectHtml = (name, values) => {
  let html = ''
  html += `<label>${name}<select id="${name}">`
  values.forEach(value => {
    html += `<option>${ value }</option>`
  })
  html += '</select></label>'
  return html
}

const selectsHtml = (selectObjects) => {
  html = ''
  for (let key in selectObjects) {
    html += selectHtml(key, selectObjects[key])
  }
  return html
}

const container = document.getElementById('container')

container.innerHTML = selectsHtml(selectObjects(variations))
<div id="container">
</div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.