1👍
Fixed event name and prop name then it should work.
-
As Vue Guide: Custom EventName says, Vue recommend always use kebab-case for event names.
so you should usethis.$emit('start-upload')
, then in the template, uses<upload-button @start-upload="upload"> </upload-button>
-
As Vue Guide: Props says,
HTML attribute names are case-insensitive, so browsers will interpret
any uppercase characters as lowercase. That means when you’re using
in-DOM templates, camelCased prop names need to use their kebab-cased
(hyphen-delimited) equivalents
so change :uploadComplete="uploadCompleteBoolean"
to :upload-complete="uploadCompleteBoolean"
Edit: Just noticed you mentioned data property=uploadingComplete.
It is easy fix, add one watch for props=uploadComplete
.
Below is one simple demo:
Vue.config.productionTip = false
Vue.component('upload-button', {
template: `<div> <button @click="onClick">Upload for Data: {{uploadingComplete}} Props: {{uploadComplete}}</button>
</div>`,
props: {
uploadComplete: {
type: Boolean
}
},
data() {
return {
uploadingComplete: this.uploadComplete
}
},
watch: { // watch prop=uploadComplete, if change, sync to data property=uploadingComplete
uploadComplete: function (newVal) {
this.uploadingComplete = newVal
}
},
methods: {
onClick() {
this.uploadingComplete = false
this.$emit('start-upload')
}
}
})
new Vue({
el: '#app',
data() {
return {
uploadCompleteBoolean: true
}
},
methods: {
upload() {
this.uploadCompleteBoolean = false
// do stuff to upload, then when finished,
this.uploadCompleteBoolean = true
},
changeStatus() {
this.uploadCompleteBoolean = !this.uploadCompleteBoolean
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<button @click="changeStatus()">Toggle Status {{uploadCompleteBoolean}}</button>
<p>Status: {{uploadCompleteBoolean}}</p>
<upload-button :upload-complete="uploadCompleteBoolean" @start-upload="upload">
</upload-button>
</div>
1👍
The UploadButton component shouldn’t have uploadingComplete
as local state (data); this just complicates the component since you’re trying to mix the uploadComplete
prop and uploadingComplete
data.
The visibility of the spinner should be driven by the parent component through the prop, the button itself should not be responsible for controlling the visibility of the spinner through local state in response to clicks of the button.
Just do something like this:
Vue.component('upload-button', {
template: '#upload-button',
props: ['uploading'],
});
new Vue({
el: '#app',
data: {
uploading1: false,
uploading2: false,
},
methods: {
upload1() {
this.uploading1 = true;
setTimeout(() => this.uploading1 = false, Math.random() * 1000);
},
upload2() {
this.uploading2 = true;
setTimeout(() => this.uploading2 = false, Math.random() * 1000);
},
},
});
<script src="https://rawgit.com/vuejs/vue/dev/dist/vue.js"></script>
<div id="app">
<upload-button :uploading="uploading1" @click="upload1">Upload 1</upload-button>
<upload-button :uploading="uploading2" @click="upload2">Upload 2</upload-button>
</div>
<template id="upload-button">
<button @click="$emit('click')">
<template v-if="uploading">Uploading...</template>
<slot v-else></slot>
</button>
</template>
1👍
Your question seems little bit ambiguë, You can use watch in that props object inside the child component like this:
watch:{
uploadComplete:{
handler(val){
//val gives you the updated value
}, deep:true
},
}
by adding deep to true it will watch for nested properties in that object, if one of properties changed you ll receive the new prop from val variable
for more information : https://v2.vuejs.org/v2/api/#vm-watch
if not what you wanted, i made a real quick example,
check it out hope this helps : https://jsfiddle.net/K_Younes/64d8mbs1/