Reputation: 3474
I need to render the same component several times with different information and when someone selects something it should load a function in the main Vue instance.
Until now I wasn't able to pass a dynamic function as a property like @change="onchange"
:
[Vue warn]: Invalid handler for event "change": got undefined
found in
---> at resources\assets\js\components\GeographyField.vue
The component:
<template>
<fieldset class="form-group col-md">
<label :for="name" class="control-label" v-html="label"></label>
<select class="form-control" :name="name" :id="name" :model="_default" :disabled="disabled" @change="onchange">
<option :value="0" v-html="placeholder"></option>
<option v-for="object in collection" :value="object.id">{{ object.name }}</option>
</select>
</fieldset>
</template>
<script>
module.exports = {
props: {
label: {
type: String,
default: 'Options'
},
_default: {
type: Number,
default: 0
},
disabled: {
type: Boolean,
default: false
},
placeholder: {
type: String,
default: 'Choose an option'
},
name: {
type: String,
required: true,
},
collection: {
type: Array,
required: true
},
onchange: {
}
},
data: function() {
return {
}
},
methods: {
}
}
</script>
The rendering:
<div class="row">
<!-- Country -->
<geography-field
label="País"
:_default="selectedCountry"
placeholder="Choose a country"
name="country"
:collection="countries"
:onchange="selectCountry()"
></geography-field>
<!-- Department -->
<geography-field
label="Departamento"
:_default="selectedDepartment"
:disabled="selectedCountry < 1"
placeholder="Choose a department"
name="department"
:collection="departments"
:onchange="selectDepartment()"
></geography-field>
<!-- Location -->
<geography-field
label="Localidades"
:_default="selectedLocation"
:disabled="selectedDepartment < 1"
placeholder="Choose a location"
name="location"
:collection="localities"
:onchange="selectLocation()"
></geography-field>
<!-- Zone -->
<geography-field
label="Zonas"
:_default="selectedZone"
:disabled="selectedLocation < 1"
placeholder="Choose a zone"
name="zone"
:collection="zones"
></geography-field>
</div>
Edit: Including selectCountry()
:
selectCountry: function() {
if(this.selectedCountry < 1) { return; }
axios.get('/get_country/' + this.selectedCountry)
.then(function (response) {
var data = response.data;
if(data.departments.length > 0) {
var departments = [];
$.each(data.departments, function (index, value) {
departments.push(value);
});
app.departments = departments;
}
});
},
How I should do to pass a function to the component properly? Any suggestions are appreciated
Edit 2: Something I might cleared up is that the components are being rendered well. Just in case I will add the component registration:
Vue.component('geography-field', require('./components/GeographyField'));
...
const app = new Vue({
Upvotes: 0
Views: 2520
Reputation: 116
To pass a function as a prop to the component, you need to strip off the trailing parentheses of the function name. Otherwise, Vue will evaluate the function. For example:
<geography-field
label="País"
:_default="selectedCountry"
placeholder="Choose a country"
name="country"
:collection="countries"
:onchange="selectCountry" // strip off the parentheses
></geography-field>
But, I would also suggest you use $emit
instead of passing a function. You can do that like so:
The component definition:
<template>
<fieldset class="form-group col-md">
<label :for="name" class="control-label" v-html="label"></label>
<select class="form-control" :name="name" :id="name" :model="_default" :disabled="disabled" @change="onchange">
<option :value="0" v-html="placeholder"></option>
<option v-for="object in collection" :value="object.id">{{ object.name }}</option>
</select>
</fieldset>
</template>
<script>
module.exports = {
props: {
label: { type: String, default: 'Options' },
_default: { type: Number, default: 0 },
disabled: { type: Boolean, default: false },
placeholder: { type: String, default: 'Choose an option' },
name: { type: String, required: true },
collection: { type: Array, required: true }
},
methods: {
onchange() {
this.$emit("onchange");
}
}
}
</script>
The component tag in the parent scope:
<geography-field
label="País"
:_default="selectedCountry"
placeholder="Choose a country"
name="country"
:collection="countries"
@onchange="selectCountry" // use @
></geography-field>
Upvotes: 5
Reputation: 20845
e.g.
:onchange="selectCountry"
Don't put ()
when you pass the function. It will trigger the function execution and whatever the function return will be pass into onchange
.
Upvotes: 1