Reputation: 2887
I am going to pass function as property to Vue component. Let it be function has to be invoked by @click
. But for some reasons I want to keep default behaviour for the component. The default behaviour is not so easy as I want and I'm going to use method
as default function. Because the default behaviour requires data from component's state (props, data, other methods, whatever).
Is there a way to do?
I've attached the example. Expected behaviour:
Button works fine
should produce alert You are welcome!
Button nope
should produce alert You are welcome as well!
but does nothing.
Vue.component('welcome-component', {
template: '#welcome-component',
props: {
name: {
type: String,
required: true,
},
action: {
type: Function,
required: false,
default: () => { this.innerMethod() },
},
},
methods: {
innerMethod() {
alert("You are welcome as well!");
}
}
});
var app = new Vue({
el: "#app",
methods: {
externalMethod() {
alert("You are welcome!");
}
}
});
#app {
margin: 20px;
}
.holder > button {
margin: 10px;
padding: 5px;
font-size: 1.1em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<welcome-component name="works fine" :action="externalMethod"></welcome-component>
<welcome-component name="nope"></welcome-component>
</div>
<script id='welcome-component' type='x-template'>
<div class="holder">
<button @click="action">{{ name }}</button>
</div>
</script>
Upvotes: 6
Views: 5521
Reputation: 794
From vue docs:
"Note that props are validated before a component instance is created, so instance properties (e.g. data, computed, etc) will not be available inside default or validator functions."
(https://v2.vuejs.org/v2/guide/components-props.html)
Referencing the innerMethod
is therefore one of the cases where the components function is not yet available.
Idea: If it is crucial for you to have this kind of functionality you could check within a later lifecycle hook (like created, mounted etc.) whether the type of action
is function
. If it's not a function (meaning not passed via prop), assign the innerMethod manually.
Upvotes: 7
Reputation: 29092
This works but it's a total bag of spanners:
action: {
required: false,
default () {
return () => this.innerMethod();
},
},
I've had to remove the type: Function
. Usually when default
is a function it will be invoked to return the appropriate default value. However, if the prop has type: Function
it'll just treat the function as the default. In this case that's problematic because we lose the this
binding.
The internal arrow function is required to get around the problem that the methods aren't available when the default
function is called.
If possible I would suggest giving up on using a default
and instead just apply the 'default' when it needs to be invoked. So rather than calling action
directly in the click
handler, instead call a method called invokeAction
that looks something like this:
invokeAction () {
if (this.action) {
this.action();
} else {
this.innerMethod();
}
}
Upvotes: 8