Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intercept checkbox change event in VueJS

I have a long set of checkboxes. I would like two groups of three of them to behave as radio buttons. Now, leaving aside my UX choices, how can I make this work?

The checkboxes are implemented as properties on a single object, layer:

data() {
  return {
    layer: {},
  }
},
watch: {
  layer: {
    handler(val, oldval) {
      mapping.updateLayers(val)
    },
    deep: true,
  },
},

That works fine. But intercepting val and updating this.layer inside handler() doesn't:

handler: function(val, oldval) {
  if (val.FutureYear) { this.layer.NextYear = false; this.layer.ExistingYear = false; }
  if (val.ExistingYear) { this.layer.NextYear = false; this.layer.FutureYear = false; }
  if (val.NextYear) { this.layer.ExistingYear = false; this.layer.FutureYear = false; }
  mapping.updateFoiLayers(val);
},

How can I achieve this result? (I'd prefer not to have to implement actual radio buttons because that makes managing all the layers and UI more complex.)

like image 391
Steve Bennett Avatar asked Jan 28 '23 17:01

Steve Bennett


1 Answers

Example: https://codepen.io/jacobgoh101/pen/NyRJLW?editors=0010

The main problem is the logic in watch.

If FutureYear is selected already, other field becomes unchangeable. Because if (val.FutureYear) is always the first one being triggered and the other 2 field will always be set to false immediately.

Another thing about watch is that it will be triggered when

  • user changed the value
  • program changed the value (this is unnecessary and make things harder to handle)

Therefore, handling @change event is more appropriate in this scenario.

JS

methods: {
    handleChange: function(e) {
      const name = e.target.name;
      if (this.layer[name]) {
        Object.keys(this.layer).map((key)=>{
          if(key != name) {
            this.layer[key] = false;
          }
        })
      }
    }
  }

html

<div id="app">
  <input type="checkbox"/ v-model="layer.FutureYear" name="FutureYear"  @change="handleChange($event)">FutureYear<br/>
  <input type="checkbox"/ v-model="layer.NextYear" name="NextYear"  @change="handleChange($event)">NextYear<br/>
  <input type="checkbox"/ v-model="layer.ExistingYear" name="ExistingYear"  @change="handleChange($event)">ExistingYear<br/>
 </div>
like image 79
Jacob Goh Avatar answered Feb 05 '23 16:02

Jacob Goh