Get each HTML element in a Vue slot from JavaScript

Viewed 1741

I am creating a custom select component in VueJS 2. The component is to be used as below by the end-user.

<custom-select>
  <option value="value 1">Option 1</option>
  <option value="value 2">Option 2</option>
  <option value="value 3">Option 3</option>
  ...
<custom-select>

I know the Vue <slot> tag and usage. But how do I get the user provided <option> tags as an array/list so I can get its value and text separately for custom rendering inside the component?

2 Answers

Those <option>s would be found in the default slot array (this.$slots.default), and you could get to the inner text and value of the <option>s like this:

export default {
  mounted() {
    const options = this.$slots.default.filter(node => node.tag === 'option')

    for (const opt of options) {
      const innerText = opt.children.map(c => c.text).join()
      const value = opt.data.attrs.value
      console.log({ innerText, value })
    }
  }
}

demo

You can achieve it, using v-bind and computed property

new Vue({
  el: '#vue',

  data: {
    selected: '',
    values: [
      {
        code: '1',
        name: 'one'
      },
      {
        code: '2',
        name: 'two'
      }
    ]
  },

  computed: {
    selectedValue() {
      var self = this;
      var name = "";
      this.values.filter(function(value) {
        if(value.code == self.selected) {
          name = value.name
          return;
        }
      })
      return name;
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="vue">
  <div>
    <select v-model="selected">
      <option v-for="value in values" v-bind:value="value.code">
        {{ value.name }}
      </option>
    </select>
  </div>
  <strong>{{ selected }} {{ selectedValue }}</strong>
</div>

Related