Estoy tratando de encontrar una manera de vincular una matriz de objetos dentro de Vue select-element. El caso es algo así como sigue:

data: {
  ideas: [
    { id: 1, code: "01A", text: "option 1", props: [] }, 
    { id: 2, code: "02A", text: "option 2 , props: [{ details: "something" }]}
  ]},
  currentForm: {
    something: "foo",
    else: "bar",
    ideaCode: "01A",
    text: "option 1"
  }
];

... y en HTML ...

<select v-model="currentForm.ideaCode" @change="setCodeAndLabelForForm(???)">
  <option v-for="i in ideas" value="i">{{ i.text }}<option>
</select>

Básicamente, necesito poder rastrear qué objeto selecciona el usuario, desencadenar mi propio evento de cambio, al mismo tiempo que tengo un enlace con una sola tecla de otro objeto ... separado de la opción / objeto seleccionado por el usuario. Nota: ¡currentForm no es el mismo tipo de objeto que la opción! Solo contiene algunas de esas propiedades que tiene la opción, y que estoy tratando de transferir a las opciones activando un evento de cambio para la selección del usuario.

El problema es que no he descubierto cómo pasar el valor seleccionado actualmente para la función O cómo escribir algo como:

<select v-model="selectedIdea" @change="setCodeAndLabelForForm" :track-by="currentForm.ideaCode">
  <option v-for="i in ideas" value="i">{{ i.text }}<option>
</select>

Un enfoque posible (y funcional) es:

<select v-model="currentForm.ideaCode" @change="setCodeAndLabelForForm">
  <option v-for="i in ideas" value="i.ideaCode">{{ i.text }}<option>
</select>

setCodeAndLabelForForm: function() {
    var me = this;
    this.ideas.forEach(function(i) {
        if(i.ideaCode == me.currentForm.ideaCode) {
            me.currentForm.ideaCode = i.selectedIdea.ideaCode;
            me.currentForm.text = i.text;
            ... do stuff & run callbacks ...
        }
    });
}

... pero parece terrible. ¿Alguna mejor sugerencia?

2
Janne 28 feb. 2018 a las 12:09

5 respuestas

No sé si esta es la mejor solución, pero resuelvo este problema usando propiedades calculadas como esta:

En el archivo JavaScript (ES6):

data () {
    return {
        options: [
            { id: 1, text: "option 1" },
            { id: 2, text: "option 2" }
        ],
        selectedOptionId: 1
    }
},
computed: {
    selectedOption () {
        return _.find(this.options, (option) => {
            return option.id === this.selectedOptionId
        });
    }
}

En el archivo HTML:

<select v-model="selectedOptionId">
  <option v-for="option in options" :value="option.id" :key="option.id">{{ option.text }}<option>
</select>

El símbolo '_' es una biblioteca JavaScript común llamada Lodash y recomiendo su uso. Puede hacerte ahorrar un tiempo precioso.

0
Augusto Escobar 28 feb. 2018 a las 10:32

Una solución un poco mejor: use index en v-for

<select v-model="selIdeaIndex" @change="setCodeAndLabelForForm">
  <option v-for="(i,idx) in ideas" value="idx">{{ i.text }}<option>
</select>

Para la js:

data: {
  selIdeaIndex:null,
  ideas: [
    { id: 1, code: "01A", text: "option 1", props: [] }, 
    { id: 2, code: "02A", text: "option 2 , props: [{ details: "something" }]}
  ]
},
methods:{
    setCodeAndLabelForForm: function() {
        var selIdea = this.ideas[this.selIdeaIndex];
        //Do whatever you wanna do with this selIdea.
    }
}
0
Fandi Susanto 8 abr. 2020 a las 10:50

Una manera humilde es usar $ref.

Hay una solución que utiliza $ref y @change.

Vue.js obtiene el objeto sin procesar de las opciones seleccionadas

0
feng zhang 15 nov. 2019 a las 09:30

Si sabe que sus option s solo vendrán de ese v-for="i in ideas", entonces los índices <option> serán los mismos que los índices item.

Por lo tanto, <select>.selectedIndex será el índice del this.item seleccionado.

new Vue({
  el: '#app',
  data: {
    ideas: [
      { id: 1, code: "01A", text: "option 1", props: [] }, 
      { id: 2, code: "02A", text: "option 2" , props: [{ details: "something" }]}
    ],
    currentForm: {ideaCode: "01A", text: "option 1"}
  },
  methods: {
    setCodeAndLabelForForm: function(selectedIndex) {
      var selectedIdea = this.ideas[selectedIndex];
      this.currentForm = {ideaCode: selectedIdea.code, text: selectedIdea.text};
    }
  }
})
<script src="https://unpkg.com/vue@2.5.13/dist/vue.js"></script>

<div id="app">
  <select v-model="currentForm.ideaCode" @change="setCodeAndLabelForForm($event.target.selectedIndex)">
    <option v-for="i in ideas" :value="i.code">{{ i.text }}</option>
  </select>
  <br> currentForm: {{ currentForm }}
</div>

Diferencias con las suyas: @change="setCodeAndLabelForForm($event.target.selectedIndex)" y la implementación setCodeAndLabelForForm.

0
acdcjunior 28 feb. 2018 a las 10:56

Puedes implementar así:

Cree datos de objetos vacíos para rastrear el valor seleccionado:

currentForm: {}

Mire currentForm en el modelo y pase el objeto seleccionado:

<select v-model="currentForm" @change="setCodeAndLabelForForm(currentForm)">

Pase el valor seleccionado en option: (estaba haciendo bien en este paso, pero acabo de cambiar i a idea ya que es un índice de bucle poco confuso)

<option v-for="idea in ideas" :value="idea">{{ idea.text }}<option>

Aplica tu método:

setCodeAndLabelForForm(selected) {
  // Now, you have the user selected object
}
2
Bhojendra Rauniyar 28 feb. 2018 a las 10:21