3
votes

I'm making a site that uses NuxtJS, Bootstrap Vue and vue-i18n.

I have a table (<b-table>) that shows areas in square meters, and the header should display: sq m in english, and m2 (m<sup>2</sup>) in a translation.

So the header field label is drawn from the i18n locale JSON to the single file component's table header label. The string is drawn correctly, but the HTML part is not rendered, unfortunately, so what I see on the page is m<sup>2</sup>.

Here's how I tried to solve it (examples are simplified - parts are deleted from them):

hu.json (translation locale file)

{
  "in_numbers": {
    "space": "m<sup>2</sup>"
  }
}

tableComponentFile.vue (single file component)

<template>
  <b-container fluid>
    <b-row>
      <b-col cols="12">
        <b-table
          :items="floors"
          :fields="tableHeader"
        />
          <template slot="HEAD_space" slot-scope="data">
            <span v-html="data.label"></span>
          </template>
        </b-table>
      </b-col>
    </b-row>
  </b-container>
</template>

<script>
export default {
  computed: {
    floors() {
      return [
        { space: 552.96 },
        { space: 796.27 }
      ]
    }
  },
  data() {
    return {
      tableHeader: [
        {
          key: 'space',
          label: this.$t('in_numbers.space'),
          sortable: false
        }
      ]
    }
  }
}
</script>

So, everything works fine, except that I cannot render the HTML from the locale json in the table header - so the table renders with the data in it, and in other components this <span v-html="$t('in_numbers.space')"></span> technique works just fine.

It doesn't work if I try (&sup2;) or anything.

The problem is that <template slot> doesn't seem to react to anything (actually I'm not sure it works) - but it should, as the documentation says (https://bootstrap-vue.js.org/docs/components/table#custom-data-rendering)

Anybody see a way to render HTML in bootstrap-vue's table header?

2

2 Answers

5
votes

Updated answer (June 2020)

Both VueJS and bootstrap-vue has changed since the question and the accepted answer was posted. It still not very clear in the bootstrap-vue docs, but you can accomplish the same result with:

<template>
  <b-container fluid>
    <b-row>
      <b-col cols="12">
        <b-table
          :items="floors"
          :fields="tableHeader">
          <template v-slot:head(space)="data"> // This has changed
            <span v-html="data.field.label"></span> // Now you access data.field.label
          </template>
        </b-table>
      </b-col>
    </b-row>
  </b-container>
</template>

<script>
export default {
  computed: {
    floors() {
      return [
        { space: 552.96 },
        { space: 796.27 }
      ]
    }
  },
  data() {
    return {
      tableHeader: [
        {
          key: 'space',
          label: this.$t('in_numbers.space'),
          sortable: false
        }
      ]
    }
  }
}
</script>
0
votes

OK, I solved it - there was an unnecessary / in the code - originally <b-table> was a self closing tag, and after I added a slot I missed to modify it.

I corrected the error, and the bootstrap-vue HEAD_ slot started working, and everything is displayed correctly now.

So, the solution looks like this:

hu.json

{
  "in_numbers": {
    "space": "m<sup>2</sup>"
  }
}

tableComponentFile.vue

<template>
  <b-container fluid>
    <b-row>
      <b-col cols="12">
        <b-table
          :items="floors"
          :fields="tableHeader"
        >
          <template slot="HEAD_space" slot-scope="data">
            <span v-html="data.label"></span>
          </template>
        </b-table>
      </b-col>
    </b-row>
  </b-container>
</template>

<script>
export default {
  computed: {
    floors() {
      return [
        { space: 552.96 },
        { space: 796.27 }
      ]
    }
  },
  data() {
    return {
      tableHeader: [
        {
          key: 'space',
          label: this.$t('in_numbers.space'),
          sortable: false
        }
      ]
    }
  }
}
</script>