[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?


Log in to reply