Search code examples
htmlvue.jsv-for

vuejs repeat a legend row to table every 25 or 50 records


I already have VueJS v-for working fine:

<tr v-for="request in requests">
    <td>{{request.name}}</td>
    <td> .. etc .. </td>
</tr>

Now I need to add a legend/guiding row say every 25 or 50 records, something like this:

<span v-for="(request, index) in requests">
    <tr>
        <td>{{request.name}}</td>
        <td> .. etc .. </td>
    </tr>
    <tr v-if="index % 25 == 0">
        <th>Name</th>
        <th> .. etc .. </th>
    </tr>
</span>

To my surprise, not only does the v-if part not work but I get back an error: "ReferenceError: request is not defined" (even if I left the v-if directive out, or even removed the extra <tr> entirely), so VueJS is making considerations on DOM structure perhaps that I don't understand yet.

Either way, how would I do this?

And by the way, is there a purely HTML/CSS way to do this?


Solution

  • Your code has invalid HTML. You can't have spans wrapping trs.

    Usually invalid HTML is not much of a big deal, but the browsers are extremelly buggy when handling invalid tr/tds placement (the spec is not clear about what they should do in case of error, so they behave each in a specific way for specific cases/errors).

    The correct approach is to use <template>s, aka "Conditional Groups":

    <table>
        <template v-for="(request, index) in requests">
            <tr>
                <td>{{request.name}}</td>
                <td> .. etc .. </td>
            </tr>
            <tr v-if="index % 25 == 0">
                <th>Name</th>
                <th> .. etc .. </th>
            </tr>
        </template>
    

    Demo reproducing your error:

    new Vue({
      el: '#app',
      data: {
        requests: [{name: 'a1'},{name: 'a2'},{name: 'a3'},{name: 'a4'},{name: 'a5'},{name: 'a6'},{name: 'a7'},{name: 'a8'}]
      }
    })
    <script src="https://unpkg.com/vue"></script>
    
    <div id="app">
    
      <table border="1">
        <span v-for="(request, index) in requests">
          <tr>
            <td>{{request.name}}</td>
            <td> .. etc .. </td>
          </tr>
          <tr v-if="index % 3 == 0">
            <th>Name</th>
            <th> .. etc .. </th>
          </tr>
        </span>
      </table>
      
    </div>

    Demo with the fix:

    new Vue({
      el: '#app',
      data: {
        requests: [{name: 'a1'},{name: 'a2'},{name: 'a3'},{name: 'a4'},{name: 'a5'},{name: 'a6'},{name: 'a7'},{name: 'a8'}]
      }
    })
    <script src="https://unpkg.com/vue"></script>
    
    <div id="app">
    
      <table border="1">
        <template v-for="(request, index) in requests">
          <tr>
            <td>{{request.name}}</td>
            <td> .. etc .. </td>
          </tr>
          <tr v-if="index % 3 == 0">
            <th>Name</th>
            <th> .. etc .. </th>
          </tr>
        </template>
      </table>
      
    </div>