vuetify: programmatically showing dialog - vue.js

vuetify says: If you want to programmatically open or close the dialog, you can do so by using v-model with a boolean value.
However I am quite unclear on what this means. Saying "using v-model" is vague at best. The parent component knows on setup if it should open but I am unclear on how to dynamically change this in the child. Am i supposed to pass it using v-bind?
<login v-bind:showDialog></login>
If so how does the child component deal with this?
Vuetify Dialog info here: https://vuetifyjs.com/components/dialogs

As I understand you have a child component which have a dialog within it. Not sure that this is 100% right, but this is how I implement it. Child component with dialog:
<template>
<v-dialog v-model="intDialogVisible">
...
</template>
<script>
...
export default {
props: {
dialogVisible: Boolean,
...
},
computed: {
intDialogVisible: {
get: function () {
if (this.dialogVisible) {
// Some dialog initialization code could be placed here
// because it is called only when this.dialogVisible changes
}
return this.dialogVisible
},
set: function (value) {
if (!value) {
this.$emit('close', some_payload)
}
}
}
in parent component we use it:
<my-dilaog :dialogVisible="myDialogVisible"
#close="myDialogClose">
</my-dialog>
data () {
return {
myDialogVisible: false
}
},
methods: {
myDialogClose () {
this.myDialogVisible = false
// other code
}
}

Дмитрий Алферьев answer's is correct but get "Avoid mutating a prop directly" warning, because when close dialog, v-dialog try change v-model to false, while we passed props to v-model and props value won't change. to prevent the warning we should use :value , #input
<template>
<v-dialog :value="dialog" #input="$emit('update:dialog',false)" #keydown.esc="closeDialog()" >
...
</v-dialog>
</template>
<script>
export default {
props: {
dialog: Boolean
},
methods: {
closeDialog(){
this.$emit('closeDialog');
}
}
In parent
<template>
<v-btn color="primary" #click="showDialog=true"></v-btn>
<keep-alive>
<my-dialog
:dialog.sync="showEdit"
#closeDialog="closeDialog"
>
</my-dialog>
</keep-alive>
</template>
<script>
data(){
return {
showEdit:false,
},
},
methods: {
closeDialog(){
this.showEdit = false;
},
}

v-model is a directive. You would use v-model, not v-bind.
The page you link has several examples. If you click on the <> button on the first one, it shows HTML source of
<v-dialog v-model="dialog">
v-model makes a two-way binding on a prop that is named value inside the component. When you set the bound variable's value to true, the dialog will display; when false, it will hide. Also, if the dialog is dismissed, it will set the variable's value to false.

Related

Buefy switch how to click on it in parent component

I have a Vue 2 app with Buefy. there is a component which contains Buefy switch. In some moment I need to click on the switch component. So I add ref property to the switch component and then I call it like this.$refs.switcherName.click(). But it throws me an error click is not a function. If I dump the $refs.switcherComponent it is component instance.
This is the code where I call the click()
watch: {
storeSelected(prevVal, newVal) {
this.$refs.onlySelectedToggler.click();
},
},
Can you be more specific on what you're trying to accomplish please? The error does tell you that "click()" is not a function of a Buefy switch, which is true. To change whether the switch is "on" or "off", you can use a v-model and data attribute to just change the value. For example:
<template>
<section>
<b-field>
<b-switch v-model="isSwitched">Default</b-switch>
</b-field>
<b-button #click="changeSwitch">Click to Change</b-button>
</section>
</template>
<script>
export default {
data() {
return {
isSwitched: false
}
},
methods: {
changeSwitch () {
this.isSwitched = !this.isSwitched
}
}
}
</script>

Vue closing component returns avoid mutating a prop directly

I have an component that I want to use on different pages. Well, it is working well till the first toggle. It shows like it used to, but when I click the 'Close' button, it closes, but console outputs :
[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: "visible"
found in
---> at src/components/Snackbar.vue
at src/views/Login.vue
And after that it doesn't show up on click
Any way to fix this?
Snackbar.vue
<template>
<v-snackbar v-model.sync="visible" :timeout="5000" bottom>
{{ content }}
<v-btn flat color="primary" #click.native="visible = false">Close</v-btn>
</v-snackbar>
</template>
<script>
export default {
name: 'snackbar',
props: [
'visible',
'content'
]
}
</script>
Login.vue
<template>
<div class="login">
<Snackbar :visible="snackbar.visible" :content="snackbar.content"></Snackbar>
</div>
</template>
<script>
import Snackbar from '#/components/Snackbar.vue'
export default {
components: {
Snackbar
},
data: function() {
return {
email: '',
password: '',
snackbar: {
visible: false,
content: ''
}
}
},
methods: {
login: function() {
if (this.email != '' && this.password != '') {
// Do something
} else {
this.snackbar.content = 'Fields can\'t be empty';
this.snackbar.visible = true;
}
}
}
}
</script>
The console error is being triggered by this:
#click.native="visible = false"
The component is directly mutating the incoming prop. If you want to keep this level of control where the parent component controls the visibility you'll have to do it by having the click event emit an event, which the parent component receives and sets this.snackbar.visible = false thereby triggering a prop change and the child component is hidden.
<Snackbar :visible="snackbar.visible" :content="snackbar.content"
v-on:requestClose="close"></Snackbar>
<v-btn flat color="primary" #click.native="$emit('requestClose')">Close</v-btn>
methods: {
close: function() {
this.snackbar.visible = false;
}
}

Change value of a props in beforeDestroy/Destroyed cycle of child component does not work

Hi I made a boolean value in parent component, and passed it to the child component as a props. it has initialized as false, and after the user view the component, the value will change to true, which means the page has been visited.
I have done some research and followed How to properly pass data from child to parent and parent to child component?
here is my js code:
<script>
export default {
props: {
hasLoad: {
type: Boolean
}
},
data () {
return {
hasLoadModel: this.hasLoad
}
},
created: function() {
console.log(this.hasLoad);
},
beforeDestroy: function() {
this.hasLoadModel = true;
this.hasLoad = true;
console.log(this.hasLoadModel);
console.log(this.hasLoad);
}
}
</script>
and html code
<div v-model="skillLoadModel">..</div>
But I still get
[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.
I have tried to change the value at either of beforeDestroy or Destroyed, or do not use v-model, but none of them works. The value has changed after I left the page, but when I reenter the page, the value has reset to default value.
Can someone help me please?
Thanks
Don't change the value of the prop. Have the component emit an event so that the parent can take the appropriate action.
Below is an example of a component that is created when the checkbox is checked, and is destroyed when it gets unchecked. The component emits a "dying" event, and the parent receives it and prints a scream to the console.
new Vue({
el: '#app',
data: {
showIt: true
},
methods: {
scream() {
console.log("Aaarg!");
}
},
components: {
myComponent: {
beforeDestroy: function() {
this.$emit('dying');
}
}
}
});
<script src="//unpkg.com/vue#latest/dist/vue.js"></script>
<div id="app">
<input type="checkbox" v-model="showIt">
<my-component v-if="showIt" hasload="true" #dying="scream" inline-template>
<div>Here I am</div>
</my-component>
</div>
I assume you're trying to communicate to the parent that the child has loaded. In that case, you can pass a function as a prop and simply call it when the child mounts.
Parent HTML:
<child :my-load-fn="loadFn"></child>
Parent JS:
methods: {
loadFn() {
this.childHasLoaded = true
}
}
Child JS:
props: ['myLoadFn'],
mounted() {
this.myLoadFn()
}

How to close dialog by self with vuejs2?

I am writing a dialog component, i don't know how to close dialog by self.
<template>
<div class="dialog" v-show="visible">
...
<button #click="close">Close</button>
</div>
</template>
<script>
{
props: {visible: {type: Boolean, default: false}},
methods: {
close () {
// this.visible = false //It will get vue warn
}
}
}
</script>
So, how to close the dialog in my component, i can't update visible prop, i will get a error.
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: "visible"
Props are one way data flow
You should not mutate the prop received from a parent component in the child component
So emit an custom event to mutate the prop in parent component itself
<template>
<div class="dialog" v-show="visible">
...
<button #click="close">Close</button>
</div>
</template>
<script>
{
props: {visible: {type: Boolean, default: false}},
methods: {
close () {
// this.visible = false //It will get vue warn
this.$emit('close-dialog')
}
}
}
</script>
parent component
<template>
<div>
<my-dialozg #close-dialog="visible = false" :visible="visible"><my-dialog>
</div>
</template>
Setup an event listener close-dialog on the dialog component and set the data property visible that you pass as a prop to false. You can do this inline as shown above or extract it into a method also
In vuejs, child component can not modify the parents property directly.
You can use events/event listeners for that. But since your example is simple you don't need an event for that.
Demo: https://jsfiddle.net/samayo/943bx5px/28/
Instead, you can pass the prop visible to your component as :visisble="visible" and watch the state change as:
watch: {
visible (val) {
if(!val) {
// close
}else{
open
}
}
}
Now, if visisble is toggled to false from the parent, your modal will not be visible.

How to send updated values from Parent component to child component in Vue JS?

I am passing a variable from parent component to child component through props. But with some operation, the value of that variable is getting changed i.e. on click of some button in parent component but I did not know how to pass that updated value to child? suppose the value of one variable is false initially and there is Edit button in parent component. i am changing the value of this variable on click of Edit button and want to pass the updated value from parent to child component.
Your property's value should be updated dynamically when using props between parent and child components. Based on your example and the initial state of the property being false, it's possible that the value was not properly passed into the child component. Please confirm that your syntax is correct. You can check here for reference.
However, if you want to perform a set of actions anytime the property's value changes, then you can use a watcher.
EDIT:
Here's an example using both props and watchers:
HTML
<div id="app">
<child-component :title="name"></child-component>
</div>
JavaScript
Vue.component('child-component', {
props: ['title'],
watch: {
// This would be called anytime the value of title changes
title(newValue, oldValue) {
// you can do anything here with the new value or old/previous value
}
}
});
var app = new Vue({
el: '#app',
data: {
name: 'Bob'
},
created() {
// changing the value after a period of time would propagate to the child
setTimeout(() => { this.name = 'John' }, 2000);
},
watch: {
// You can also set up a watcher for name here if you like
name() { ... }
}
});
You can watch a (props) variable with the vue watch.
for example:
<script>
export default {
props: ['chatrooms', 'newmessage'],
watch : {
newmessage : function (value) {...}
},
created() {
...
}
}
</script>
I hope this will solve your problem. :)
Properties, where the value is an object, can be especially tricky. If you change an attribute in that object, the state is not changed. Thus, the child component doesn't get updated.
Check this example:
// ParentComponent.vue
<template>
<div>
<child-component :some-prop="anObject" />
<button type="button" #click="setObjectAttribute">Click me</button>
</div>
</template>
<script>
export default {
data() {
return {
anObject: {},
};
},
methods: {
setObjectAttribute() {
this.anObject.attribute = 'someValue';
},
},
};
</script>
// ChildComponent.vue
<template>
<div>
<strong>Attribute value is:</strong>
{{ someProp.attribute ? someProp.attribute : '(empty)' }}
</div>
</template>
<script>
export default {
props: [
'someProp',
],
};
</script>
When the user clicks on the "Click me" button, the local object is updated. However, since the object itself is the same -- only its attribute was changed -- a state change is not dispatched.
To fix that, the setObjectAttribute could be changed this way:
setObjectAttribute() {
// using ES6's spread operator
this.anObject = { ...this.anObject, attribute: 'someValue' };
// -- OR --
// using Object.assign
this.anObject = Object.assign({}, this.anObject, { attribute: 'someValue' });
}
By doing this, the anObject data attribute is receiving a new object reference. Then, the state is changed and the child component will receive that event.
You can use Dynamic Props.
This will pass data dynamically from the parent to the child component as you want.