1

I'm a total noob on Vue.js and I'm trying to build some kind of pretty customized options selector.

My data-binding works fine but I can not figure out how class-binding works for checking each node's value.

HTML:

<div id="pretty_options">
  <ul class="pretty-options" data-field="field_id">
    <li class="option" v-on:click="select" v-bind:class="{ selected : isSelected }" data-value="1">One</li>
    <li class="option" v-on:click="select" v-bind:class="{ selected : isSelected }" data-value="2">Two</li>
    <li class="option" v-on:click="select" v-bind:class="{ selected : isSelected }" data-value="3">Three</li>
    <li class="option" v-on:click="select" v-bind:class="{ selected : isSelected }" data-value="4">Four</li>
    <li class="option" v-on:click="select" v-bind:class="{ selected : isSelected }" data-value="5">Five</li>
  </ul>
  <input type="number" id="field_id" name="field_id" v-model="field_id">
</div>  

JS:

var mcveSample = new Vue({
  el: '#pretty_options',
  data: {
    field_id: 1
  },
  methods: {
    select: function(event) {
      var option = event.currentTarget;
      var value = option.dataset.value;
      this.field_id = value;
    }
  },
  computed: {
    isSelected: function(element) {
      // I'd like to do something like this:
      // return this.field_id == element.dataset.value;
      // But, I can't find how to check each element's value...
    }
  }
});

Here's a JSFiddle.

So, my question is: How do I compare with every node's value/attribute on a computed function?

1 Answer 1

2

Computed property returns a value based on another data property or computed value. In your case you should use a method which accepts a li index as an argument and returns true/false, or just check equality inline.

Also, you can use v-for to generate list items:

var mcveSample = new Vue({
  el: '#pretty_options',
  data: {
    field_id: 0,
    options: ['One', 'Two', 'Three', 'Four', 'Five']
  },
  methods: {
    select: function(index) {
      this.field_id = index;
    }
  }
});
.option {
  display: inline-block;
  list-style: none;
  margin: 1em;
  padding: 0.25em 1em;
  background-color: #ccc;
  border-radius: 1em;
  cursor: default;
}
.selected {
  background-color: red;
}
<script src="https://unpkg.com/vue"></script>
    
<div id="pretty_options">
    <ul class="pretty-options" data-field="field_id">
      <li class="option" 
        v-for="(option, index) of options" // create li from your array
        v-on:click="select(index)" 
        v-bind:class="{ selected : index == field_id }" // check inline for example
        v-bind:data-value="index">{{ option }}</li>
    </ul>
    <input type="number" id="field_id" name="field_id" v-model="field_id">
</div>

If you prefer method and/or you need more complex logic, you can do it like this:

v-bind:class="{ selected : isSelected(index) }"

And define this method:

methods: {
  isSelected: function(index) {
    return index == this.field_id
  },
//...other methods
}

or it is better to use computed property which returns function

computed:{
  isSelected: function() {
    return function(index){
       return index == this.field_id;
    }
  },
  //...other computed propertues
}

Documentation

computed properties are cached based on their dependencies

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

4 Comments

Thank you so much for this broad explanation!
Excuse me, wostex. I'm implementing it now and I face another issue... What if I can't use a v-for (options rendered in server side) or an index (data-value being a string also rendered server side...)
@JordiNebot well, select will still work, but you need to pass your index to isSelected somehow. If you want to render template on server I guess you can hardcode indexes: jsfiddle.net/wostex/uvon90La It's not very optimal though.
This is a great answer!

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.