serge
serge

Reputation: 15219

get v-select text on select

I saw some documentation on v-select and slots, but didn't really understand if I can apply it for my example codepen.

I just need to get the selected text (not the value), and use it somewhere in the code:

new Vue({
  el: "#app",
  vuetify: new Vuetify(),
  data: {
    state: {},
    selectedText: "",
    states: [
      { value: "a", text: "alpha" },
      { value: "b", text: "beta" },
      { value: "g", text: "gamma" }
    ]
  },
  methods: {
    change: (newValue) => {
      // do something with the text
      // "alpha", "beta", or "gama"
      console.log(newValue);
    }
  }
});
<link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet"/>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.js"></script>
<div id="app">
  <v-app id="inspire">
    <v-container fluid>
      <label>my selected text is: {{state}}</label>
      <v-row align="center">
        <v-col cols="3">
          <v-select v-model="state" :items="states" @change="change" :text="selectedText"></v-select>
        </v-col>
      </v-row>
    </v-container>
  </v-app>
</div>

Upvotes: 1

Views: 796

Answers (3)

serge
serge

Reputation: 15219

EDIT: The best option I found is to use a computed property for the selected text, without changes to the current code (go in FullPage after lauching the snippet to correctly see the output):

new Vue({
  el: "#app",
  vuetify: new Vuetify(),
  data: {
    countries: [
      { code: "a", name: "Ameriga Fatela" },
      { code: "b", name: "Bolivia Grande" },
      { code: "c", name: "Comore Potentia" }
    ],
    country: "b"
  },
  methods: {
    getCountryCode() {
      return "c"; // have no c.name here!
    },
    change() {
      this.country = this.getCountryCode();
    }
  },
  computed: {
    countryName() {
      return this.countries.find((c) => c.code === this.country).name;
    }
  }
});
<link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.js"></script>
<div id="app">
  <v-app>
    <v-container>
      <div>current code is &gt;{{country}}&lt;</div>
      <div>current name is &gt;{{countryName}}&lt;</div>
      <v-row>
        <v-col cols="12">
          <v-select v-model="country" :items="countries" item-text="name" item-value="code"></v-select>
          <v-btn @click="change">change by script to '{{getCountryCode()}}'</v-btn>
          </vcol>
      </v-row>
    </v-container>
  </v-app>
</div>

Another option is (Codepen here) the suggestion of Anurag Srivastava to use return-object, I returned the object. However, it have some drawbacks, cause actually I am not able to properly change the value by code:

new Vue({
  el: "#app",
  vuetify: new Vuetify(),
  data: {
    country: "c",
    countries: [
      { code: "a", name: "Ameriga Fatela" },
      { code: "b", name: "Bolivia Grande" },
      { code: "c", name: "Comore Potentia" }
    ]
  },
  methods: {
    getCountryCode() {
      return "b"; // have no c.name here!
    },
    change() {
      var newCode = this.getCountryCode();
      this.country = newCode;
    }
  }
});
<link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.js"></script>
<div id="app">
  <v-app>
    <v-container>
      <div>current code is &gt;{{country.code}}&lt;</div>
      <div>current name is &gt;{{country.name}}&lt;</div>
      <v-row>
        <v-col cols="12">
          <v-select v-model="country" :items="countries" item-text="name" item-value="code" return-object></v-select>
          <v-btn @click="change">change by script to 'b'</v-btn>
          </vcol>
      </v-row>
    </v-container>
  </v-app>
</div>

However, in both cases we should recalculate the country name. That is not good. Imagine to build the combobox we have to do a heavy operation... recalculating it each time is time-consuming and really not optimal....

Upvotes: 0

Anurag Srivastava
Anurag Srivastava

Reputation: 14413

You need to add return-object prop to <v-select>

new Vue({
  el: "#app",
  vuetify: new Vuetify(),
  data: {
    state: null,
    selectedText: "",
    states: [
      { value: "a", text: "alpha" },
      { value: "b", text: "beta" },
      { value: "g", text: "gamma" }
    ]
  },
  methods: {
    change: (newValue) => {
      // do something with the text
      // "alpha", "beta", or "gama"
      console.log(newValue.text);
    }
  }
});
<link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet"/>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.js"></script>
<div id="app">
  <v-app id="inspire">
    <v-container fluid>
      <label>my selected text is: {{state && state.text}}</label>
      <v-row align="center">
        <v-col cols="3">
          <v-select :items="states" v-model="state" @change="change" item-text="text" return-object></v-select>
        </v-col>
      </v-row>
    </v-container>
  </v-app>
</div>

Edit: Ok so based on your approach, the solution would be to use the country code to find appropriate country object in the country list and set that.

Here is how you would solve it:

new Vue({
  el: "#app",
  vuetify: new Vuetify(),
  data: {
    country: "c",
    countries: [{
        code: "a",
        name: "Ameriga Fatela"
      },
      {
        code: "b",
        name: "Bolivia Grande"
      },
      {
        code: "c",
        name: "Comore Potentia"
      }
    ]
  },
  methods: {
    getCountryCode() {
      return "b"; // have no c.name here!
    },
    change() {
      var newCode = this.getCountryCode();
      // Since we were getting objects when changing options, we must also set objects 
      this.country = this.countries.filter(country => country.code === newCode)[0];
    }
  }
});
<link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.js"></script>
<div id="app">
  <v-app>
    <v-container>
      <div>current code is &gt;{{country.code}}&lt;</div>
      <div>current name is &gt;{{country.name}}&lt;</div>
      <v-row>
        <v-col cols="12">
          <v-select v-model="country" :items="countries" item-text="name" item-value="code" return-object></v-select>
          <v-btn @click="change">change by script to 'b'</v-btn>
          </vcol>
      </v-row>
    </v-container>
  </v-app>
</div>

Upvotes: 1

aseidma
aseidma

Reputation: 752

Your states objects contain both value and text properties. If you change value to key v-select recognizes the change and you can access the text property via this.state. Like so:

new Vue({
  el: "#app",
  vuetify: new Vuetify(),
  data: {
    state: {},
    selectedText: "",
    states: [
      { key: "a", text: "alpha" },
      { key: "b", text: "beta" },
      { key: "g", text: "gamma" }
    ]
  },
  methods: {
    change: (newValue) => {
      // do something with the text
      // "alpha", "beta", or "gama"
      console.log(newValue); // Also returns text attribute instead of key
    }
  }
});
<div id="app">
  <v-app id="inspire">
    <v-container fluid>
      <label>my selected text is: {{state}}</label>
      <v-row align="center">
        <v-col cols="3">
          <v-select v-model="state" :items="states" @change="change"></v-select>
        </v-col>
      </v-row>
    </v-container>
  </v-app>
</div>

Upvotes: 0

Related Questions