Search code examples
javascriptvue.jsbootstrap-4bootstrap-vue

Bootstrap-vue b-table passing @row-clicked data to a b-card *outside* the table or template?


Working on a Boostrap-Vue b-table that uses the @row-clicked to display related data in a card that expands down below the clicked row in the table. That works wonderfully, but now the client asks if that data could appear to the side of the table, like a in a sidebar b-card.

I've tried moving the <template #row-details="row">...</template> outside of the b-table and into a b-card like so:

  <b-table :items="dataDevices" @row-clicked="onRowClicked">
    <!-- normally the template is in here and works as expected  -->
  </b-table> 
  <template #row-details="row">
    <b-card>{{ row.item.serno }}</b-card>
  </template>

But that doesn't work. I've tried changing the template syntax to read <template slot="row-details" slot-scope="row"> but to no avail.

I would like to think my Google-Fu is pretty good, but so far I can't seem to find anyone that's tried it this way.

I understand that @row-clicked contains a pointer to the row data, and that obviously works with templates inside the b-table object, but I'd think we should be able to pass row data to areas outside b-table.

Has anyone experimented with visualizing b-table row data this way? And if so, how did you do it?

Maybe I need to write an event handler function for @row-clicked that 'passes' the data to a b-card with a specific id? Just shooting ideas in the dark at this point.

Any pointers in the right direction or links to examples or documentation would be appreciated.


Solution

  • As you mention, the @row-clicked event sends the item object of the clicked row.

    That means you can use this object, and save it to a local property in data. This property can then be used outside of the table, like in a <b-card>.

    new Vue({
      el: "#app",
      data() {
        return {
          fields: ["isActive", "first_name", "last_name", "age"],
          items: [{
              isActive: true,
              age: 40,
              first_name: 'Dickerson',
              last_name: 'Macdonald'
            },
            {
              isActive: false,
              age: 21,
              first_name: 'Larsen',
              last_name: 'Shaw'
            },
            {
              isActive: false,
              age: 89,
              first_name: 'Geneva',
              last_name: 'Wilson'
            }
          ],
          selectedItem: null
        }
      },
      methods: {
        onRowClicked(item) {
          this.selectedItem = item
        }
      }
    })
    <link href="https://unpkg.com/bootstrap@4.5.3/dist/css/bootstrap.min.css" rel="stylesheet" />
    
    <script src="https://unpkg.com/vue@2.6.12/dist/vue.min.js"></script>
    <script src="https://unpkg.com/bootstrap-vue@2.21.2/dist/bootstrap-vue.js"></script>
    
    <div id="app" class="p-3">
      <b-row>
        <b-col>
          <b-table :items="items" :fields="fields" bordered @row-clicked="onRowClicked" class="mb-0"></b-table>
        </b-col>
        <b-col>
          <b-card class="h-100">
            <pre v-if="selectedItem">{{ selectedItem }}</pre>
            <h4 class="text-center" v-else>
              No item selected.
            </h4>
          </b-card>
        </b-col>
      </b-row>
    </div>