How to have a page with or without q-drawer



  • You don’t need v-if for the drawer’s visibility. You just need to control the v-model of the drawer appropriately. Something like on Page X, allow for it to toggle as it should. For Page Y, always keep it false. Oh, and however you do the “calculation”, you’ll also need it to hide show the drawer button too and that could be in a v-if. 😉

    Scott



  • Thank you Scott for the extra info. Currently looking into Vuex as that is a requirement to get it all to work together properly.



  • @qyloxe I was wondering if keeping the active tab, which represents a page in the routes.js, in a Vuex state variable is the best solution. Say for example you save the activeTab in the vuex store on a click:

    <q-route-tab to="/tickets" label="Tickets" @click="activeTab='tickets'" />
    

    The above example will work when clicking on the q-tab but not when you go directly to the page with copy pasting a url like http://localhost:8080/#/tickets. At that moment there is no click event for Vue to set the store state variable.

    So I was wondering, is the router not aware what page is loaded? Isn’t this stored somewhere? It would seem logical that the router would know what the active page is, that is the one I need to set the drawer to show/hide or its content.

    Have to look into this. Any tips are wlcome 🙂



  • Yeah, so you’re going to need to “find” a piece of data related to the page itself to make the decisions on. Maybe use the route path? Or set meta data on the page within the route? I’m just guessing though.

    https://router.vuejs.org/guide/advanced/meta.html#route-meta-fields

    Scott



  • Depending on the route would be the best way to go. But how does the <q-tabs> component know whcih tab is active? As the active tab is underlined correctly every time. It needs to be the same logic I suppose.



  • If the tab is being set properly via the router, then there you have it. Use the QTab’s v-model to set your drawer logic too.

    Scott



  • That’s some clever thinking! I’ll try that approach it seems to the the best one. I was already looking at lifecycles too. Like say in the ‘Mounted’ section of a page set the Vuex state variable. I don’t even know if this would’ve been possible as a page is not a component I believe. Sorry for the confusion, I’m still learning.

    Thank you for the great help. Really appreciate it Scott.



  • Well, it’s all about the “reactiveness” of Vue, which is very clever. 🙂 You should always try to think in terms of how to “hook” into the data reactiveness in as many situations as you can, This is a paradigm change, where, in the old days prior to reactive UI frameworks, you had to somehow always “trigger” the actions you wanted to happen yourself. Thinking in the sense of reactive programming is often missed by a lot of devs coming to Vue or React. It’s one of the first concepts I learned in order to understand the greatness of having a Vue or React using data flow to “react” to (and of course where the name React came from 🙂 ).

    https://en.wikipedia.org/wiki/Reactive_programming

    Scott



  • Thank you Scott, that’s valuable advice. As a newbie it will take me a while before I got ‘the right mind set’. But I’m sure with lots of failing will also come some success. So thanks for being so helpful. In any case,

    I was doubting between Nuxt and Quasar because I wanted to have some easier development than with plain Vue.js. I fell a bit in love with bootstrap along the way too, but Quasar adopted the same techniques so that will be very similar. I love the classes and components that are availble in Quasar out of the box. Quasar just seemed more an all in one solution than Nuxt. Might be wrong on that but I know my bosses at work. It starts with a simple website and then a few months down the road they might say “Could you make it a mobile app?” or something similar. So i think this is the right framework.

    Thank you again for takng the time to help me out. Stay home, stay safe.



  • PS: I never get email notifications from the forum upon replies although I marked is a ‘Watched’. Checked my mail address and it’s correct. Just a heads-up that there might be something wrong with the forum.



  • One last question with regards to the basic layout/design. Suppose you have your ‘routes.js’ configured like this:

    const routes = [
      {
        path: '/',
        component: () => import('layouts/MainLayout.vue'),
        children: [
          { path: '', component: () => import('pages/Index.vue') },
          { path: 'about', component: () => import('pages/About.vue') },
          { path: 'links', component: () => import('pages/Links.vue') }
        ]
      },
      {
        path: '/tickets',
        component: () => import('layouts/MainLayout.vue'),
        children: [
          { path: '', component: () => import('pages/tickets/Index.vue') },
          { path: 'myTickets', component: () => import('pages/tickets/MyTickets.vue') },
          { path: 'newTicket', component: () => import('pages/tickets/NewTicket.vue') },
          { path: 'followUp', component: () => import('pages/tickets/FollowUp.vue') },
        ]
      },
    

    In this case we’re using the same component ‘MainLayout.vue’ for both parent paths. Given that we want to have a custom drawer we could decicde to create a new ‘layout’ containing the custom side bar just for ‘Tickets’ for example. However, as this side bar will be having the same location. styling, … on all pages it is better to have this in the ‘MainLayout.vue’ as we discussed before and populate/set the drawer depening on the route (or q-tabs v-model).

    One question here: if we use the same ‘MainLayout.vue’ component for both parent folders does it get reloaded when changing routes between say ‘/’ and ‘/tickets/myTickets’? Because that would be unnessary as the layout is the same, only the drawer’s content is updated and the page component is changed/loaded. What I mean is there’s no reasyon to reload the header for example.



  • Correct. Unless the layout is going to change majorly between sections of your app, you should stick to one layout, if possible. It is why it is chock full of features too. 🙂

    Thanks for the bit about the emails here in the forum. We’ll check on it.

    Scott



  • @DarkLite1 said in How to have a page with or without q-drawer:

    One question here: if we use the same ‘MainLayout.vue’ component for both parent folders does it get reloaded when changing routes between say ‘/’ and ‘/tickets/myTickets’? Because that would be unnessary as the layout is the same, only the drawer’s content is updated and the page component is changed/loaded. What I mean is there’s no reasyon to reload the header for example.

    I can only guess but this one could be helpful:
    https://router.vuejs.org/guide/essentials/nested-routes.html

    You can have one layout which you register as main “route” layout and the subpath routes could be registered to specific areas of this layout. Be it for example tabs.

    Routing could be misleading and not obvious, it is VERY helpful to register global hooks and just “console.log” what is happening when you change routes:
    https://router.vuejs.org/guide/advanced/navigation-guards.html#global-before-guards

    In case of specific components, when you need to “react” on route changes in some specific way, there is a possibility to “watch” for route changes in ANY component. It is in documentation, but this post is very recommended:
    https://blog.webf.zone/vue-router-the-missing-manual-ce51c21430b0?gi=b45747cfc34f

    Oh, and two another pitfalls:

    1. the “keep-alive” - there are a situtations, when you prefer to have one component assigned to subroutes “kept” in memory by Vue. This helps.
    2. async components - this could be nasty, and again, if you want to mix that with router, there are some solutions (hacks), where you need to use this:
      https://vuejs.org/v2/api/#Vue-nextTick


  • Thanks guys, really appreciate the input. I’ve also read the suggestion from qylozee about nested routes and taking into account Scott’s remark about keeping it in one layout if possible then I think this router setup would be more suited to have the header and footer not re-rerended on route changes because they all use the same MainLayout:

    const routes = [
      {
        path: '/',
        component: () => import('layouts/MainLayout.vue'),
        children: [
          { path: '', component: () => import('pages/Index.vue') },
          { path: 'about', component: () => import('pages/About.vue') },
          { path: 'links', component: () => import('pages/Links.vue') },
          { path: 'tickets/myTickets', component: () => import('pages/tickets/MyTickets.vue') },
          { path: 'tickets/newTicket', component: () => import('pages/tickets/NewTicket.vue') },
          { path: 'tickets/followUp', component: () => import('pages/tickets/FollowUp.vue') },
        ]
      },
    


  • I’ve been struggling with the keeping the navigation link on top of the site active when a link in the drawer (side bar navigation) had been clicked. As this would call another page the Vue router simply removed the ‘active’ class from the tab and only set it in the drawer:

    <q-tabs v-model="activeTab" align="left">
            <q-route-tab
              v-for="link in navigationLinks"
              :key="link.name"
              :name="link.name"
              :to="link.to"
              :label="link.label"
              :class="{ 'my-menu-link': link.name === activeTab }"
              exact
            />
          </q-tabs>
    

    I thought about fixing this with using a simple <q-tab> instead of a <q-route-tab> like so:

    <q-tabs v-model="activeTab" align="left">
            <q-tab
              v-for="link in navigationLinks"
              :key="link.name"
              :name="link.name"
              :to="link.to"
              :label="link.label"
              :class="{ 'my-menu-link': link.name === activeTab }"
              exact
            />
          </q-tabs>
    

    Luckily for me this works just fine, except when you copy/paste a link in the addrees bar of the browser. To solved this, I read the docus on hooks as posted by qyloxe. Thanks for the that by the way. So now I’m planning to keep the tab ‘Tickets’ in the header toolbar active if a child route has been called with the string ‘/tickets/’ in its link.

    router.beforeEach((to, from, next) => {
    // match the string in the link and set the vuex store state accordingly
    })
    

    Oops… while testing this further I noticed the pages are not reached but the tab is colored and stays colored 🙂 Up to the drawingboard again to get this right. Better some pain now than having bigger app issues later on.

    faa4a05f-af03-4a07-aacb-acb0450f223a-image.png

    It would be great if <q-router-tab v-model=“activeTab”> would be able to keep its value, also on moving away from the route. Something like “if activeTab is set, you can’t set it to null”. That way it’s easy to keep the correct tab highlighted.



  • I’ll do it the other way around using a hook in the router that will set the acrive classes on the <q-router-tab> whenever the route is matched. It will be easier Ithink 🙂

    q-router-link--exact-active 
    q-router-link--active 
    q-tab--active 
    


  • Would you be interested in making a codesandbox with some of your code to test the navigation and to collaborate on? https://codesandbox.quasar.dev

    Scott



  • I’d love that. Never used the codesandbox before. I’ve just registered and clicked on your link to create a proof of concept (if I can). Is this normal? Or did I do something wrong?

    a7183e4f-ddfb-4cc0-b2f2-582924d4b69b-image.png



  • Did you fork it? You’ll need to fork it.

    Scott



  • Thanks Scott, I finally figured out how to use it. Great tool you guys have! Really really really cool that you can share code like this.

    Feel free to have a look if you want.


Log in to reply