q-page shows under q-header



  • MainLayout.vue

    <template>
    <q-layout view=“lHh lpR lFf”>
    <q-header reveal elevated class=“mobile-only”>
    </q-header>
    <q-header class=“mobile-hide”>
    </q-header>
    <q-drawer
    </q-drawer>
    <q-page-container>
    <router-view />
    </q-page-container>
    <q-footer elevated class=“mobile-only”>
    </q-footer>
    </q-layout>
    </template>

    Page.vue

    <template>
    <q-page padding>
    <p>This content is under the q-header on mobile. Why?</p>
    </q-page>
    </template>



  • You have a typo in <q-drawer> tag, miss closing “>”



  • Sorry, it was accidentally omitted the closing “>” on this post, but I do have it in the acutal page. So, assuming my closing tags are all properly set, my question remains… why does the content of q-page-container start UNDER the q-header on MOBILE-HIDE and works perfectly for q-header on MOBILE-HIDE?



  • You meant that you haven’t any drawer in mobile?



  • No, drawer works perfectly in mobile. What I’m saying is that this content: <p>This content is under the q-header on mobile. Why?</p> is not visible because it is covered by the <q-header> on mobile. To see the content, I added this: <div style=“height:50px;” class=“mobile-only” /> to move the <p> 50 pixels lower to show below the <q-header>. Shouldn’t ALL of the content in the Page.vue file be seen just below the header and NOT have the header covering it up? It works correctly in desktop – content actually begins below the <q-header>, but mobile it is hidden.



  • @qwedia Have you found a solution to this issue? I’m having the same problem.



  • @Hamid Do you make sure that your page component is wrapped in a <q-page> tag?



  • @beets

    <template>
      <q-page class="q-pa-md">
        <q-header elevated class="bg-yellow">
          <q-toolbar>
            <q-btn flat round dense icon="arrow_back_ios" text-color="grey" class="q-mr-sm" @click="$router.go(-1)"/>
            <q-toolbar-title class="text-grey text-center text-bold">Options</q-toolbar-title>
            <q-btn flat round/>
          </q-toolbar>
        </q-header>
        <h6 class="text-bold text-grey">{{surah.name_simple}}</h6>
        <q-list bordered separator class="surah-list">
            <q-item clickable v-ripple @click="$router.push({ name: 'select-aya-from', params: { surah: surah } })">
              <q-item-section>
                <q-item-label>Aya from</q-item-label>
              </q-item-section>
            </q-item>
            <q-item clickable v-ripple @click="$router.push({ name: 'select-aya-to', params: { surah: surah } })">
              <q-item-section>
                <q-item-label>Aya to</q-item-label>
              </q-item-section>
            </q-item>
        </q-list>
      </q-page>
    </template>
    

    The q-header is inside the q-page.
    One thing to note is that it only happens if I’m using keep-alive on router-view and only when you navigate back to the page which has the q-header.
    The problem doesn’t occur on the first page load but if you navigate away and then back, you will see that they q-page is underneath q-header.

    Capture.JPG



  • @Hamid Your q-header should be a direct child of q-layout. There’s two good options to doing this.

    First option

    Use vue-router named views. In this case, you separate the page body and header into settings-page.vue (root tag is q-page) and settings-header.vue (root tag is q-header). In your routes file, something like this:

    const router = new VueRouter({
      routes: [
        {
          path: '/settings',
          components: {
            default: () => import('pages/settings-page.vue'),
            header: () => import('pages/settings-header.vue'),
          }
        }
      ]
    })
    

    and in MainLayout.vue:

    <template>
      <q-layout view="lHh Lpr lFf">
    
        <router-view name="header" />
    
        <q-drawer>
          ...
        </q-drawer>
    
        <q-page-container>
          <router-view />
        </q-page-container>
    
      </q-layout>
    </template>
    
    

    That will inject the settings-header.vue component into the first router-view and the page into the second router-view. This way you can make different headers, or no header at all, based on the route.

    Read more: https://router.vuejs.org/guide/essentials/named-views.html

    Second option

    Use vue-portal. In this case, you keep the q-header in your current component, but wrap it in a portal tag. In your settings component, it would look like this:

    <template>
      <q-page class="q-pa-md">
    
        <portal to="header">
          <q-header elevated class="bg-yellow">
            <q-toolbar>
              <q-btn flat round dense icon="arrow_back_ios" text-color="grey" class="q-mr-sm" @click="$router.go(-1)"/>
              <q-toolbar-title class="text-grey text-center text-bold">Options</q-toolbar-title>
              <q-btn flat round/>
            </q-toolbar>
          </q-header>
        </portal>
    
        <h6 class="text-bold text-grey">{{surah.name_simple}}</h6>
        <q-list bordered separator class="surah-list">
           ....
        </q-list>
    
      </q-page>
    </template>
    

    And in main layout:

    <template>
      <q-layout view="lHh Lpr lFf">
    
        <portal-target name="header"></portal-target>
        
        <q-drawer>
          ...
        </q-drawer>
    
        <q-page-container>
          <router-view />
        </q-page-container>
    
      </q-layout>
    </template>
    
    

    For this, you must install with yarn add portal-vue then make a boot file at src/boot/portal.js with contents:

    import PortalVue from 'portal-vue'
    export default({ Vue }) => {
      Vue.use(PortalVue)
    }
    

    And make sure to add 'portal' to the boot array in quasar.conf.js

    Read more: https://github.com/LinusBorg/portal-vue

    For your case, I probably recommend the first option as it is built in to vue-router. I would recommend the second case if the header needed to call methods of the page, or share data that you don’t want in vuex, etc.


Log in to reply