How to close child dialog dynamically
-
Hi, i have a parent component that creates a child dialog and I would like to close the dialog dynamically from the child. I have tried many things but it doesn’t work.
Parent
<template> <q-dialog v-model="signInDialog" @closeSignInDialog="signInDialog = false" persistent transition-show="flip-down" transition-hide="flip-up" > <login></login> </q-dialog> </template> <script lang="ts"> import Login from 'components/Login.vue' import { defineComponent, ref } from '@vue/composition-api'; export default defineComponent({ name: 'MainLayout', data () { return { signInDialog: false } }, components: { Login }, setup() { const leftDrawerOpen = ref(false); return {leftDrawerOpen} } }); </script>
Child:
methods: { async onSubmit () { await dispatchLogIn(this.$store, {username: this.email, password: this.password}) if (readLoginError(this.$store)) { // fail this.$q.notify({ color: 'negative', position: 'top', message: 'Incorrect email or password', icon: 'report_problem' }) }else{ ----> this.$emit("closeSignInDialog") } } }, });
What am I doing wrong ?
-
What if you put the code from your login component directly in your q-dialog? Does it work then?
If so maybe this will help:
https://github.com/quasarframework/quasar/issues/5822 -
@dobbel
Im not sure I understand, if I copy my login component (child) directly into my q-dialog (parent) then i wont have a child/parent, only parent so it should work ? -
Well yes because every thing( including the on submit code) is in 1 component so you don’t have to emit events. You can change
signInDialog
directly:async onSubmit () { await dispatchLogIn(...) if (readLoginError(this.$store)) { // fail this.$q.notify({ color: 'negative', position: 'top', message: 'Incorrect email or password', icon: 'report_problem' }) }else{ ----> this.signInDialog = false <--- } }
-
ok let me clarify. These are 2 different vue files. (im a noob in vue)
Parent: pages/main.vue
<template> <q-dialog v-model="signInDialog" @closeSignInDialog="signInDialog = false" persistent transition-show="flip-down" transition-hide="flip-up" > <login></login> </q-dialog> </template> <script lang="ts"> import Login from 'components/Login.vue' import { defineComponent, ref } from '@vue/composition-api'; export default defineComponent({ name: 'MainLayout', data () { return { signInDialog: false } }, components: { Login }, setup() { const leftDrawerOpen = ref(false); return {leftDrawerOpen} } }); </script>
Child : components/Login.vue
<template> ... </template> <script> ... methods: { async onSubmit () { await dispatchLogIn(this.$store, {username: this.email, password: this.password}) if (readLoginError(this.$store)) { // fail this.$q.notify({ color: 'negative', position: 'top', message: 'Incorrect email or password', icon: 'report_problem' }) }else{ ----> this.$emit("closeSignInDialog") } } }, }); </script>
I don’t want to move my code from login.vue component to main.vue page.
Does it makes sens ?
-
I don’t want to move my code from login.vue component to main.vue page.
Ah I see.
I personally use Vuex to solve these kind of problems. I am not a vue event expert, but using a q-dialog with custom components requires some extra work:
-
I just figured it out because you made me think. You rock!
I ended moving my <dialog> into my login component itself and then adding a props “showDialog” that i can set from parent
Child : components/Login.vue
<template> <q-dialog ---> v-model="showDialog" persistent transition-show="flip-down" transition-hide="flip-up" > ... </template> <script> ... props: { --> showDialog: { default: false, type: Boolean, }, }, methods: { async onSubmit () { await dispatchLogIn(this.$store, {username: this.email, password: this.password}) if (readLoginError(this.$store)) { // fail this.$q.notify({ color: 'negative', position: 'top', message: 'Incorrect email or password', icon: 'report_problem' }) }else{ ---> this.showDialog = false } ... </script>
and then on parent : pages/main.vue
<template> <login :showDialog="showSignInDialog"></login> </template> <script> ... data () { return { showSignInDialog: false } }, </script>
-
Great! Yes that’s also a way to prevent using events.
I thought a little about it and I might know what the problem is in your original code. From Vue’s perspective the q-dialog is the parent of your custom login component.
Because your login component is emitting the event you should also let your login component expose the
@closeSignInDialog
instead of your q-dialog:(I might be totally wrong here)<template> <q-dialog v-model="signInDialog" persistent transition-show="flip-down" transition-hide="flip-up" > <login @closeSignInDialog="signInDialog = false"></login> </q-dialog> </template>
A better name for the event would be ‘loginSucces’ or something since the login component is not aware of it’s parent q-dialog.
-
Yup it makes sense, but I think I prefer to have my dialog inside my component.
And I like your name suggestion for the event.
Thx again for your help.