Search code examples
html-tablevue.jsv-for

Vue table in one loop html


I have an array, with sizes of shoes and quantity each of them in shop, structure like this:

array = {
    36=>1,   
    37=>0,
    38=>5,
    39=>2
}

In my table key in this table ( here 36, 37 ... ) are TH, and value is TD. I can't do this in one loop. I tried like this:

<table class="table">
    <tr>
        <th v-for="(quantity, key) in productSizes" :key='key'>{{key}}</th>
    </tr>

    <tr>
    <td>Here should be quantity for each size<td>
    </tr>

</table>

Is there a possibility to do this at once?

Here is structure how it should look like (there is an input, because someone can change quantity).

enter image description here


Solution

  • I cannot conceive of a way you could do this in one loop, nor do I think it's worth the effort. Just loop a second time over the same data structure and you will always get matching columns.

    console.clear()
    
    const shoeSizes = {
      36: 0,
      37: 2,
      38: 1,
      39: 3,
      40: 2,
      41: 0
    }
    
    new Vue({
      el: "#app",
      data:{
        shoeSizes
      }
    })
    <script src="https://unpkg.com/vue@2.4.2"></script>
    <div id="app">
      <table>
        <tr>
          <th v-for="quantity, key in shoeSizes">{{key}}</th>
        </tr>
        <tr>
          <td v-for="quantity, key in shoeSizes">
            <input type="text" v-model="shoeSizes[key]">
          </td>
        </tr>
      </table>
    </div>

    Assuming there were even 100 shoe sizes the performance impact would be negligible.

    Edit

    Well, I can think of one way you could render it in one loop. Using a render function.

    console.clear()
    
    const shoeSizes = {
      36: 0,
      37: 2,
      38: 1,
      39: 3,
      40: 2,
      41: 0
    }
    
    new Vue({
      el: "#app",
      data:{
        shoeSizes
      },
      render(h){
        let headers = [], cells = []
        // build the headers and cells
        for (let key of Object.keys(this.shoeSizes)){
          // header is easy
          headers.push(h('th', key))
          
          // build props for the input to implement v-model
          let vmodel = {
            domProps: {
              value: this.shoeSizes[key]
            },
            on: {
              input: event => {
                this.$set(this.shoeSizes, key, event.target.value) 
                this.$emit('input', event.target.value)
              }
            }
          }
          // add the vell
          cells.push(h('td', [h('input', vmodel)]))      
        }
        // render the table with headers and cells in the 
        // right places
        return h('table', [h('tr', headers), h('tr', cells)])
      }
    })
    <script src="https://unpkg.com/vue@2.4.2"></script>
    <div id="app"></div>

    This render function builds the headers and cells in the same loop and then renders the table around them. But I think you would agree this is needlessly complex.