Reputation: 7129
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"/> 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)?
Upvotes: 6
Views: 10225
Reputation: 20805
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">
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
.
Here is an example that puts it all together. In this example we see
field
component containing a single checkbox. It fires a change
event when the checkbox is changed, and passes on event.target.checked
event.target.checked
)field
components are created. Each one uses a different handlerVue.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>
Upvotes: 8