[Solved] [V1] $emit working in one case, not another
-
Working: a page has a QDialog defined like this:
<q-dialog v-model="showWorkflow" @escape-key="onWorkflowRunDismiss" content-style="background-color: #FFFFFF;" maximized > <div> <h5 v-if="showWorkflow" class="q-pl-lg q-py-sm bg-deep-purple-14 glossy text-white" style="margin-bottom: 0; margin-top: 0px; width: 100%;" > <q-icon v-if="selected" slot="header" name="fas fa-cogs" size="24px" class="q-mr-sm" /> {{ selected.name }} <div class="float-right" > <q-btn flat dense rounded aria-label="Close" label="Close" class="q-px-md" @click="onWorkflowRunDismiss" > <q-icon name="far fa-times-circle" class="q-ml-sm" /> </q-btn> </div> </h5> <report-params-toolbar v-if="selected" :selected-workflow="selected" /> <component id="workflowComponent" v-if="showWorkflow" :is="selected.componentName" :rpt-name="selected.name" style="margin-left: 0px; margin-right: 0px;" /> </div> </q-dialog> // in code section created () { this.$root.$on('workflowFacChange', this.workflowFacChange) }, // in methods section: workflowFacChange () { console.log('receiving') this.nursingAreas = [] this.facility = this.$store.state.pharmAssist.selectedFac this.allPatients = [] this.getPatients() },
The report-params-toolbar has the $emit and looks like this:
<template> <div style="text-align: center" > <q-btn-dropdown :label="selectedFacLabel" icon="fas fa-hospital-alt" type="button" size="md" color="deep-purple-14" text-color="white" glossy push no-wrap class="q-mr-sm q-mt-xs" > <q-list link v-if="facilityOptions.length > 0" separator > <q-item v-for="(facility, index) in facilityOptions" :key="index" dense v-close-popup @click.native="onSelectedFacilityClick(index)" > <q-item-label class="text-weight-bold text-grey-14">{{ facility.label }}</q-item-label> </q-item> </q-list> </q-btn-dropdown> </div> </template> // in code section: methods: { onSelectedFacilityClick (id) { this.facility = this.facilityOptions[id].value this.selectedFacLabel = this.facilityOptions[id].label this.$store.dispatch('pharmAssist/setSelectedFac', this.facility).then(() => { console.log('sending') this.$root.$emit('workflowFacChange', this.facility) }) } }
What doesn’t work is this:
<q-dialog maximized class="modalBG" v-model="showParams" @escape-key="onReportRunDismiss" content-style="background-color: #FFFFFF" > <report-params /> </q-dialog> // in the code section: created () { console.log('register this crap') this.$root.$on('showReport', this.onShowReport) this.$root.$on('facilityName', this.onFacilityName) }, // in the methods section: onFacilityName (val) { console.log('updating fac name', val) this.facilityName = val }, onShowReport (val) { console.log('showing report', val) this.showReport = val }
And the report-params component:
<template> <div> <h5 class="q-pl-lg q-py-sm bg-blue-10 glossy text-white shadow-3" > <q-icon slot="header" name="fas fa-cogs" size="24px" class="q-mr-sm" /> Set parameters and run </h5> <div class="q-mx-lg" > <q-card id="report-type-selection" bordered > <q-card-section class="q-pb-none" > <q-icon color="positive" name="mdi-numeric-1-box" style="font-size: 32px;" /> <span class="text-h6 q-ml-sm">Report Type</span> </q-card-section> <q-card-section> <q-option-group type="radio" color="negative" v-model="singleMulti" :options="[ { label: 'Single Patient', value: 'single' }, { label: 'Multiple Patients', value: 'multiple' } ]" @change="storeSingleMultiPat" inline class="q-mt-sm q-ml-lg" /> <span class="text-caption q-ml-xl">Select the report type</span> </q-card-section> </q-card> <q-card v-show="singleMulti === 'multiple'" id="report-facility-selection" bordered > <q-card-section class="q-pb-none" > <q-icon color="positive" name="mdi-numeric-2-box" style="font-size: 32px;" /> <span class="text-h6 q-ml-sm">Facility</span> </q-card-section> <q-card-section> <q-select v-model="facility" :options="facilityOptions" @input="facilitySelected" style="width: 100%" class="q-pl-xl" /> </q-card-section> </q-card> <q-card v-show="singleMulti === 'multiple'" id="report-department-selection" bordered > <q-card-section class="q-pb-none" > <q-icon color="positive" name="mdi-numeric-3-box" style="font-size: 32px;" /> <span class="text-h6 q-ml-sm">Nursing Areas</span> </q-card-section> <q-card-section> <q-option-group type="radio" color="negative" v-model="nAPlusMinus" :options="[ { label: 'Include', value: 'plus' }, { label: 'Exclude', value: 'minus' } ]" inline @input="setNAPlusMinus" class="q-mt-sm q-ml-lg" /> <q-separator /> <q-select v-model="nursingAreas" multiple use-chips chips-bg-color="blue-10" use-input input-debounce="0" clearable @filter="filterFn" separator :options="deptOpts" @input="setNursingAreas" style="width: 100%" /> <span>No selection = all nursing areas; Type to filter by area name</span> </q-card-section> </q-card> </div> <div class="float-left q-ml-lg q-mt-md" > <q-btn id="runReportButton" color="negative" glossy rounded push label="Run" @click="onReportRunAcceptRP" class="q-mr-sm" /> <q-btn label="Cancel" glossy rounded push @click="onReportRunDismiss" class="q-mr-sm bg-blue-10 text-white" v-close-popup /> </div> </div> </template>
// from the methods section: onReportRunAcceptRP (event) { // TODO use the else case to show error, or disable ok button if (this.facility !== null) { console.log('emitting') this.$root.$emit('facilityName', this.facilityOptions.find(obj => obj === this.facility).label.substring(7)) this.$root.$emit('showReport', true) } },
I believe I already tried replacing this.facilityName and this.showReport with Vuex entries but had other issues.
Anything stand out to you guys as wrong? Note that in v 0.17, I had the same code in a QModal for each of the above QDialogs with no issues.
I know support here is spotty since Quasar hasn’t blown up in popularity yet, but I appreciate when you guys are able to comment.
-
BTW, there are no error messages generated. I’m also using the desktop version of Vue Developer Tools, but nothing ever shows up on the Events tab, whether related to the above or anything else. I would think that something somewhere in my app would cause an event. Very strange.
-
you could use codesandbox or codepen sample https://codepen.io/TruckTurner/pen/qqpRyq.
I think at report-params component is where you should listen to your child component emitted event.... <report-params @workflow-fac-change="doSomethingWithTheEmittedData"/> ... methods: { doSomethingWithTheEmittedData(data) { //where data is facility } } ...
i’m not sure about the use of root coz usually i’ll just use this.$emit(…) to pass a data back to parent component. some vue docs https://vuejs.org/v2/guide/components.html#Listening-to-Child-Components-Events & https://vuejs.org/v2/guide/components-custom-events.html.
-
I’ll give that a try. In this case it is parent-child, I suppose. The $root version I was trying to use (and which worked in 0.17) is supposed to allow one to have any vue file talk to any other - presumably if they are both active in the DOM. Sibling components, for example, could respond to events from each other. Or grandparents.
-
maybe set up the $root listener at a REAL root, such as App.vue (if you want it everywhere)
-
Also, always remember to destroy your listeners:
beforeDestroy () { // Don't forget to turn the listener off before your component is destroyed this.$root.$off('openLeftDrawer', this.openLeftDrawerCallback) }
https://v1.quasar-framework.org/options/global-event-bus#Introduction
-
@metalsadman that is working for a test page I worked up. I’ll try it in my original code too now. Incidentally, my test page, which basically duplicates the working case without any extra stuff in it, also doesn’t work using $root. I’m very puzzled.
@nothingismagick perhaps I’m misunderstanding how the $root case works: https://v1.quasar-framework.org/options/global-event-bus#Introduction — I thought this meant that I could simply use $root and $on and $off as I was doing with no issues. Perhaps I should look at the code in 0.17 and V1 and compare behind the scenes. Maybe something did change there in how this was implemented. I’m not sure which files might be where to start, but I’ll try.
Also, I did have the beforeDestroy, thanks. I just didn’t show it here since that doesn’t directly make it not work.
-
@metalsadman, @nothingismagick I just had an “aha” moment. In my working case, the two files are siblings! They are both components in a parent file. In the non-working case, the $emit was in the child and the parent was supposed to receive it. Same with the test case I worked up that was otherwise identical to the working case. Adjusting the child-parent cases to use @metalsadman’s suggestion worked for both of them.
The sibling case using $root still works. I’m going to see if I can come up with another sibling case and see if that will work too. If it does, it begs the question: what changed in V1 to disallow using $root.$emit in a child-parent case?