How to use a parent (Dialog) component



  • Hi,

    I would like to create a default parent component from a QDialog. I have created a component/DefaultDialog.vue:

    <template>
      <q-dialog ref="defaultDialog" @hide="onDialogHide">
        <q-card>
          <q-card-section class="row text-white bg-primary q-pa-sm">
            <div class="text-h6 q-pl-sm">{{title}}</div>
            <q-space/>
            <q-btn v-close-popup flat round dense icon="close"/>
          </q-card-section>
    
          <form @submit.prevent="saveForm">
            <q-card-section>
              <!-- dynamic section.. I want to use slots to fill this section -->
              <slot></slot>
            </q-card-section>
    
            <q-card-actions align="right" class="inset-shadow q-pr-md">
              <q-btn label="Save" color="primary" type="submit"/>
            </q-card-actions>
          </form>
        </q-card>
      </q-dialog>
    </template>
    
    <script>
    export default {
      name: 'DefaultDialog',
    
      props: ['title'],
    
      methods: {
        show() {
          this.$refs.defaultDialog.show()
        },
        hide() {
          this.$refs.defaultDialog.hide()
        },
        onDialogHide() {
          this.$emit('hide')
        },
        saveForm() {
          this.$emit('saveForm')
        }
      }
    }
    </script>
    

    Now I want to use it and tried this ‘components/UserDialog2.vue’:

    <template>
      <default-dialog>
        <q-input outlined label="Name"/>
      </default-dialog>
    </template>
    
    <script>
    import DefaultDialog from 'components/DefaultDialog'
    
    export default {
      mixins: [DefaultDialog],
      components: {
        DefaultDialog
      }
    }
    </script>
    
    

    I want to open the dialog using:

    this.$q.dialog({
       component: UserDialog2,
       parent: this
    })
    

    When its opened the input is not shown.
    I have created a full codesandbox app: https://codesandbox.io/s/reusable-dialog-component-nkdfn
    Here you can find: components/UserDialog.vue

    I want to split the dialog part so I can reuse it.
    Therefore I have create components/UserDialog2.vue. this uses components/DefaultDialog.vue
    I think I am almost there but something went wrong. There comes an error: ‘Error in mounted hook: “TypeError: this.$refs.defaultDialog is undefined”’

    Does anybody have got a idea?
    Thanks!



  • From my understanding, you are mixing 2 distinct things. Using slots mean that you’ll your component into the template. But you want to call it from the plugins.

    On my projects, I use pug for that purpose (https://pugjs.org/).
    You can split the code from the template, write a DefaultDialog component, a DefaultDialog template. Then, create your UserDialog2 than extends DefaultDialog component and DefaultDialog template.

    // DefaultDialog.pug
    q-dialog(ref="dialog" @hide="onDialogHide" :persistent="true")
      q-card
          block title
           q-card-section.row.text-white.bg-primary.q-pa-sm
            .text-h6.q-pl-sm {{title}}
            q-space
            q-btn(v-close-popup flat round dense icon="close")
          form @submit.prevent="saveForm"
            q-card-section
             block content
          q-card-actions(align="right").inset-shadow.q-pr-md
            q-btn(label="Save" color="primary" type="submit")
    

    for DefaultDialog.vue refer to the plugin: https://quasar.dev/quasar-plugins/dialog#Invoking-custom-component but without a template:

    then for UserDialog2:

    <template lang="pug">
      extends DefaultDialog
        block content
          div your-content-here
    </template>
    <script>
    import DefaultDialog from 'DefaultDialog'
    export default {
      name: 'UserDialog2',
      extends: DefaultDialog
    }
    </script>
    

    As it’s a extends, you can overload methods, etc. to perform whatever you never on Ok, Cancel, etc.



  • Hi,

    Thanks for you idea’s. I have tried to implement it by adding a new UserDialog3.vue in the codesandbox https://codesandbox.io/s/reusable-dialog-component-nkdfn

    This generates an error: Component template requires a root element, rather than just text.
    Googling about this error I find out pug might be installed. So I have tried to install it following this document: https://quasar.dev/quasar-cli/cli-documentation/handling-webpack#Pug
    I have runed the command yarn add --dev pug pug-plain-loader

    and changed the build section in quasar.conf.js :

        build: {
          scopeHoisting: true,
          vueRouterMode: 'history',
          extendWebpack (cfg) {
            cfg.module.rules.push({
              test: /\.pug$/,
              loader: 'pug-plain-loader'
            }),
            chainWebpack (chain) {
              chain.module.rule('pug')
                .test(/\.pug$/)
                .use('pug-plain-loader')
                  .loader('pug-plain-loader')
            }        
          }      
        },
    

    Now I keep getting a 502 error: 502 Bad Gateway. We had trouble connecting to the server, try restarting it or check the logs to see what happened.
    I have tried to remove the pug settings from the quasar.conf.js, but this does not work. I cannot find the log either.

    Any idea’s?



  • I guess you don’t need both rules.

     extendWebpack (cfg) {
            cfg.module.rules.push({
              test: /\.pug$/,
              loader: 'pug-plain-loader'
            })
    }
    

    should be enough



  • Hi @jraez ,

    Thanks for your help! I have tried it, but it is still broken.
    I didn’t like the dialog plugin approach, so have recreated a similar topic with a different approach: https://forum.quasar-framework.org/topic/5541/how-to-extend-a-dialog

    Perhaps you can look into this?


Log in to reply