Reputation: 2966
I create an alert component in vue, like this
<template>
<div class="alert-bg" v-if="view">
<div class="content">
<div class="message"> {{message}} </div>
<div class="alert-control text-right mt-4">
<button class="btn btn-secondary" @click="onCancel" v-html="cancel"/>
<button :class="btnStyle" class="btn ml-2" v-html="ok" @click="onSubmit"/>
</div>
</div>
</div>
</template>
<script>
import $ from 'jquery';
import 'imports-loader?window.jQuery=jquery,this=>window!widgster';
export default {
name: 'Alert',
props: {
message: { default: 'Lorem ipsum dolor sit amet consectetur' },
cancel: { default: 'Cancel' },
ok: { default: 'Yes' },
btnStyle: { default: 'btn btn-primary' },
view: { default: false }
},
methods: {
onCancel(){
this.view = false;
},
onSubmit(){
this.$emit('onSubmit');
}
},
};
</script>
then in main page I use it like this,
// html
<button class="btn btn-secondary" @click="confirm" v-html="'Confirm'"/>
<Confirm :view="alert.view"/>
// script
import Confirm from '@/components/modals/alert/alert';
export default {
name: "Product",
components: { Confirm },
data() {
return {
alert: { view: false },
}
},
methods: {
confirm(){
this.alert.view = true; // show alert
}
}
}
When I click confirm button, it's success to show alert, when I click cancel button the alert is close but I got error like this
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "view"
then when I click confirm button again, the alert does not appear, how I can solve this problem? thank you very much
Upvotes: 0
Views: 215
Reputation: 161
As vue.js guide says:
All props form a one-way-down binding between the child property and the parent one: when the parent property updates, it will flow down to the child, but not the other way around. This prevents child components from accidentally mutating the parent’s state, which can make your app’s data flow harder to understand.
So you have to create component own state and and then modify state inside your component. Like this:
<script>
import $ from 'jquery';
import 'imports-loader?window.jQuery=jquery,this=>window!widgster';
export default {
name: 'Alert',
data() {
return{
componentView: this.view
}
},
props: {
message: { default: 'Lorem ipsum dolor sit amet consectetur' },
cancel: { default: 'Cancel' },
ok: { default: 'Yes' },
btnStyle: { default: 'btn btn-primary' },
view: { default: false }
},
methods: {
onCancel(){
this.componentView = false;
},
onSubmit(){
this.$emit('onSubmit');
}
}
};
</script>
Upvotes: 0
Reputation: 2759
You are changing the prop directly from the child component(as vue said). So the true way is:
methods: {
onCancel(){
// this.view = false; <--- is wrong way
this.$emit('update:view', false)
}
// ...
},
Then in parent pass it like this:
<Confirm :view.sync="alert.view"/>
Upvotes: 1