2

I have a string pipe of values, which I want to modify. the string pipe has a range from 0-5 values, so I made the following:

new Vue({
  el: '#app',
  data: {
    valuesString: ""
  },
  computed: {
    values: {
      get() {
      	var values = this.valuesString ? this.valuesString.split("-") : [];
        if(values.length < 5)
        	values.push(null);
        return values;
      },
      set(values) {
        this.valuesString = values.filter(value => value).join("-")
      }
    }
  }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="app">
  <div v-for="(value, i) in values" :key="i">
    <select v-model="values[i]" style="width: 200px">
      <option></option>
      <option>1</option>
      <option>2</option>
      <option>3</option>
      <option>4</option>
      <option>5</option>
    </select>
  </div>
  <br>
  <span>valuesString: {{ valuesString }}</span>
  <br>
  <span>values: {{ values }}</span>
</div>

The problem now is, that the setter of my computed values property getn't called.

my usecase is a filter like a categories filter. I get the valuesString as parameter from my router. The user should be able to select 1-5 categories to filter. every time the filter changes the router paramter should change and a new empty select should appear until there are 5 categories set.

2
  • If I understand correctly, you want the user to be able to select up to a maximum of five categories and build those selected categories into a string? Commented Aug 29, 2017 at 16:00
  • exactly, because the string is a param of my route, so after a site refresh or a change of the route, my selects should be already set (or change) Commented Aug 30, 2017 at 9:06

2 Answers 2

1

I'm not entirely sure I understand what you are looking for, but I think this will do the trick:

  • Parse the piped string and place it in an array
    • See the computed property unpiped
  • loop through the array and place the value in the selectbox
    • the loop should occur on the . The result is bound to valuesString
  • The selected value should be pushed to a results array and the selectbox should be cleared.
    • see the pushValues method.

Jfiddle example

<div id="app">
 <div>
   <select v-model="valuesString" @change="pushValues" style="width: 200px">
    <option v-for="p in unpiped">{{p}}</option>
    </select>
  </div>
<br>
  <span>valuesString: {{ valuesString }}</span>
<br>
  <span>unpiped: {{ unpiped }}</span>
 <br>
   <span>results: {{ results }}</span>
</div>

JS:

new Vue({
el: '#app',
 data: {
  valuesString: "",
  piped: "1|2|3|4|5",
  results: []
 },
 computed: {
  unpiped(){
    var v = this.piped.split("|");
    return v;
 },
},
 methods: {
   pushValues: function(){
    this.results.push(this.valuesString)
    this.valuesString = ""
 }
}
});
Sign up to request clarification or add additional context in comments.

Comments

0

maby my question wasn't clear. Bert's comment is right

I solved my problem with a workaround, but I'm not so satisfied. maby anyone can help me to optimize it. For this I tried to use computed setters.

new Vue({
  el: '#app',
  data: {
    values: [],
    valuesString: "",
    allValues: [...Array(5).keys()]
  },
  watch: {
    values (val) {
      if(val.toString() != this.filteredValues.toString()  && val.toString() != this.filteredValues.concat([null]).toString())
        this.$set(this, 'values', this.filteredValues);
      else if (this.valuesString != this.filteredValues.join('-'))
        this.$set(this, 'valuesString', this.filteredValues.join('-'));
    },
    valuesString (valuesString) {
      this.$set(this, 'values', valuesString.split('-'));
    }
  },
  computed: {
    filteredValues () {
      return this.values.filter(v => v);
    },
    modelArray () {
      let size = this.filteredValues.length;
      if(size < 5)
        size++;
      return new Array(size);
    }
  }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="app">
  <div v-for="(value, i) in modelArray" :key="i">
    <select v-model="values[i]" style="width: 200px">
      <option></option>
      <option v-for="(v, j) in allValues" :key="j" v-if="v == values[i] || filteredValues.indexOf(v.toString()) === -1">{{ v }}</option>
    </select>
  </div>
  <br>
  <span>valuesString: <input v-model="valuesString" /></span>
  <br>
  <span>values: {{ values }}</span>
  <br>
  <span>filteredValues: {{ filteredValues }}</span>
</div>

Comments

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.