Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic click handler for Vue.js component?

Tags:

vue.js

I've been developing a generic Field component for use in forms in a Vue web app I'm developing. In my EditProduct component, for example, I have multiple instances of the Field component, some of them of type 'checkbox', some 'text', etc. Effectively what the checkbox variant does is generate something like this:

<div class="col-xs-2">
    <label>
        <input id='organic' name='organic' type="checkbox" v-model="product.organic"/>&nbsp;Organic
    </label>
</div>

from this:

<field :cols="2" name="organic" v-model="product.organic" type="checkbox"></field>

That's much simplified, but shows the general idea. What I'd like to be able to do is to pass something like a 'change' handler function name as a prop, like this:

<field :cols="2" name="organic" v-model="product.organic" type="checkbox" change="this.handleSomething"></field>

This would call a function in the EditProduct component. I'm not sure how to get this to work, though. I already have a change handler method in my Field component which is there to emit the notification event:

methods: {
    handleCheckbox: function (event) {
        this.$emit('input', event.target.checked);
        if(this.change){
           //do something here...
        }

    }
}, 

My idea was to test for the existence of a 'change' prop here and then do something, but all I have at this point is a string containing the name of a function. How do I actually use this to call a function, preferably with an argument derived from $event (such as $event.target.checked, say)?

like image 349
John Moore Avatar asked Dec 01 '16 19:12

John Moore


People also ask

What is dynamic component in Vue?

js Dynamic Components allows the users to switch over the components without updating the route of the Vue. js application itself. It also keeps the data in its current state. It is useful when the user is in a tabbed interface.

Is Vue synchronous or asynchronous?

Conclusion. Vue updates the DOM asynchronously; tests runner executes code synchronously instead.

What is watch handler Vue?

A Watcher is a useful and special feature provided by VueJs to watch over a component or data property and perform specific actions when the value of the component or data property is changed. It is the most generic and recommended way to react over a data change in a vue instance.


1 Answers

Use $emit and v-on to comunicate from child to parent

Rather than passing in a handler, emit an event from your Field component when the internal value changes. Then, using v-on, you can register a handler for that event.

Here is the documentation for $emit. Usage: this.$emit('event-name', arguments...)

Here is the documentation for v-on. Usage: <component v-on:event-name="handler">


Also use v-on on the input element

You can also use v-on to register handlers for default events. For example, an input element will fire a change event when it is changed. Thus,

<input type="checkbox" v-on:change="onChange"/>

will cause onChange to fire when the checkbox changes. Note that arguments are automatically passed into the handler. So, in this case, the event is passed into onChange.


Example

Here is an example that puts it all together. In this example we see

  • a field component containing a single checkbox. It fires a change event when the checkbox is changed, and passes on event.target.checked
  • a root vue instance with two event handlers. They expect a boolean value (the result of event.target.checked)
  • in the html, two field components are created. Each one uses a different handler

Vue.component('field', {
  template: '#field',
  data: function() {
    return {
      value: null
    }
  },
  methods: {
    onChange: function(event) {
      // emit a change event
      // Provide event.target.checked as an argument
      this.$emit('change', event.target.checked);
    }
  }
})

new Vue({
  el: '#app',
  data: {
    selected1: false,
    selected2: false
  },
  methods: {
    changeHandler1: function(selected) {
      this.selected1 = selected;
    },
    changeHandler2: function(selected) {
      this.selected2 = selected;
    },
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.3/vue.js"></script>

<div id="app">
  <p>Selected1: {{selected1}}</p>
  <p>Selected2: {{selected2}}</p>
  
  <!-- Register a handler for the 'change' event -->
  <field v-on:change="changeHandler1"></field>
  <field v-on:change="changeHandler2"></field>
</div>

<template id="field">
  <!-- 
       By default, the input element fires a change event  
       when it is modified. The event is automatically passed  
       into the handler. 
  -->
  <input type="checkbox" v-on:change="onChange"/>
</template>
like image 68
asemahle Avatar answered Nov 15 '22 08:11

asemahle