0

So, I need to generate x amount of "selects" based on a result from a query to an external endpoint.

Below is an example of the json that is the data I use to generate my selects. This example contains only one "question" in an array of "questions". (Also, the array construct inside the "answers" is a little bit exaggerated but that's what I have to work with)

"questions": [{
    "question": [
    {
       "answers": [
        {
          "answer": [
            {
              "answer": "Answer 1",
              "id": 216,
              "questionID": 83,
              "selected": false,
              "sortOrder": 1
            },
            {
              "answer": "Answer 2",
              "id": 217,
              "questionID": 83,
              "selected": true,
              "sortOrder": 2
            },    
            ... plus x number of "answers" here..           
          ]
        }
       ],
       "question": "Question 1",
     }
    ]}
 ...]

So, I generate the selects like so (I have stripped the example from irrelevant styling):

<v-layout row wrap v-for="question in questionnaire.questions[0].question" 
:key="question.id">  
      <span>{{question.question}}</span>

      <v-select
        item-text="answer"
        item-value="id"
        :items="question.answers[0].answer"
        ref="answer_selects"    
      ></v-select>

Now, back to my question. As you can see in the json the second "answer" has a property "selected" with the value of "true". This means that I have to set this particular item as selected "by default". How do I achieve this in a good vue manner?

1
  • Use the prop value for that. Commented Sep 13, 2019 at 20:07

1 Answer 1

1

If you only want to set it as a default value, vou can use the :value-Property and just pass the first Object from the answer-array that has selected set to true.

:value="question.answers[0].answer.find(answer -> answer.selected)"

Note that when using that the value is not bound to what is selected, so if you select a different item the data in the parent component will not update! If you want it automatically updated, you should consider using v-model along with computed-properties.

Edit: Ok so I've looked into your question a bit deeper and I think I came up with a pretty good solution.

First of all, I don't really understand the properties you set in the v-select component, since none of them are defined in the VueSelect Api. In this answer I use the properties defined there. Also, I'm not quite sure how to interpret your data structure, so I'll just give an example with a array of questions which contains an id, a question text and an array of answers.

In order to use v-model with a computed property you have to to implement a getter which will be called to set the v-select-component data and a setter for updating the data when a different item is selected in the select-component. Since in your case you would have to have one computed property for each element in the questions-array, you should wrap the display of a question-object into its own component and display multiple of those in a loop.

Vue.component('v-select', VueSelect.VueSelect);
Vue.component("question", {
  "template": "#questionTemplate",
  "props": {
    "question": Object
  },
  "computed": {
    "selectedId": {
      "get": function() {
        return this.question.answers.find(answer => answer.selected).id;
      },
      "set": function(id) {        
        //set selected flag on newly selected element
        this.question.answers.find(answer => answer.id === id).selected = true;
        //reset previous choice
        this.question.answers.find(answer => answer.selected && answer.id !== id).selected = false;
      }
    }
  }
});

new Vue({
  "el": "#app",
  "data": function() {
    return {
      "questions": [
        {
          "id": 83,
          "question": "QuestionText",
          "answers": [
            {
              "answer": "Answer 1",
              "id": 216,
              "questionID": 83,
              "selected": false,
              "sortOrder": 1
            },
            {
              "answer": "Answer 2",
              "id": 217,
              "questionID": 83,
              "selected": true,
              "sortOrder": 2
            }
          ]
        }
      ]
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/vue-select@latest"></script>
<link rel="stylesheet" href="https://unpkg.com/vue-select@latest/dist/vue-select.css">

<div id="app">
  <question v-for="question in questions" :question="question" :key="question.id"></question>
</div>

<script type="text/x-template" id="questionTemplate">
  <div>
    <p>{{question.question}}</p>
    <v-select
      v-model="selectedId"
      :options="question.answers" 
      label="answer"
      :reduce="answer => answer.id"></v-select>
      
      <p>Selected AnswerId: {{selectedId}}</p>
  </div>
</script>

If you want to be able to select multiple values, the VueSelect-component will return an array of IDs instead of one single ID, sou you woukd have to adjust the computed getter and setter accordingly.

Hope I could help, let me know if you need any further help!

Sign up to request clarification or add additional context in comments.

3 Comments

Could you elaborate on how to use v-model and computeds? I noticed that if I put a v-model="something" on my selects the result is that whenever I select something in a select all the other selects lose their selected value..so they go blank so to speak...
What I didn't show in my example is that I also create checkboxes dynamically from some types of questions that are "multiple choice". These checkboxes I can bind to a v-model which holds all the checkboxes answer-id in an array.. But for the selects it doesn't appear to work that way...
Thank you! Even though I solved it in another manner (by using the $refs where the selected item is available) I think this looks like a more vue-ish solution. The reason why you don't understand the properties is probably because I'm on vuetify 1.5 instead of the current 2.0-something... :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.