Is there a community-recommended mechanism for freely navigating ".vue" files whilst still taking advantage of <v-ons-tabbar> for primary navigation?



  • I have a “small” project that makes use of the <v-ons-tabbar> for navigation on the surface. It works very well. However, on a couple of pages, I’d like to navigate freely to other “.vue” template locations (not necessarily in the same file). Is it recommended to use some combination of vue router and navigator, or is there some mechanism I have yet to discover?

    FYI, I have seen a few examples of combining “navigator” with “tabbar”, but it makes the assumption that every template is in the same large file, and that all activity occurs from the standpoint if the initial template.

    In an effort to give the “monolithic” approach a try, on one of my “tabbar”-controlled pages, I tried the following:

    <template id="main">
      <v-ons-navigator :page-stack="pageStack">
        <component :is="page" v-for="page in pageStack" :page-stack="pageStack"></component>
      </v-ons-navigator>
    </template>
    
    <template id="project_list_page">
      <v-ons-page>
        PROJECT LIST
      </v-ons-page>
    </template>
    
    <template id="project_rooms_list_page">
      <v-ons-page>
        SUB ITEMS LIST (HOPEFULLY IN THE CONTEXT OF THE PRESSED PROJECT ITEM
      </v-ons-page>
    </template>
    
      const projectListPage = {
        template: '#project_list_page',
        props: ['pageStack']
      };
    
      const projectRoomsListPage = {
        template: '#project_rooms_list_page',
        props: ['pageStack']
      };
    
      export default{
        template: '#main',
        data(){
          return{
            'projects':[],
            'pageStack':[projectListPage]
          }
        },
    ...
    ...
    ...
    

    NOTE: while I’m sure it’s not the issue, I’ve tried all permutations of ‘pageStack’ and the id/page names with and without quotes. And while I receive no errors, nothing seems to work (i.e. it won’t load “projectListPage”).

    I’m sure I’m missing something simple in the monolithic example. And, I’ll stick to the monolithic if it’s absolutely necessary, but I’d really like to be able to separate pages and functionality between “.vue” files while maintaining the look and benefits of Onsen navigation/tabbar.


  • Onsen UI

    @humblecoder take a look at this. In this repo I’m implementing some common navigation patterns for all bindings such as the one you need in Vue, as Monaca projects (with separate source files).

    Hopefully I will add them shortly to our tutorial but there only the ‘monolithic’ approach as you call it works, although I admit it may sometimes not be straightforward to split it in different files.



  • @misterjunio, as far as I can tell, that is EXACTLY what I’m looking for. More straightforward than I expected. I’ll have to make some “navigational” decisions, but still very nice. And yes, you should add it to the tutorial section asap. Much appreciated.


  • Onsen UI

    @humblecoder I think you could have a look at the kitchen sink example. Make sure you are in the no-vuex branch. It uses vue files and there is no limitation with it.



  • @Fran-Diox there are some valuable nuggets in each of your repos, but I think @misterjunio is closer to what I’m looking for. Basically I need the ability to go as far down the “sub-page” rabbit hole as desired, and still find my way back. Still, much appreciated.



  • @misterjunio I’m sure I’ve just been staring at all this too long and probably need to take a step back. But, would you guys mind providing a bit more insight into just where “pageStack” comes from and how it is actually supposed to be implemented? I mean, is it necessary to have it initiated in the primary VUE object, or can we bring about a pageStack anywhere in the process? Must we call it “pageStack”?


  • Onsen UI

    @humblecoder pageStack is just the name we chose for the array that ‘controls’ the navigator, so it is a required prop in the component where you define it, yes. Basically the page that is displayed is always the last element of that array, and when you push a new page or pop one the corresponding animation is performed.

    I’m not sure what is confusing you but of course in <v-ons-navigator :page-stack="pageStack"> your variable may have a different name (e.g. :page-stack="pages", where pages is your array) but the :page-stack binding to <v-ons-navigator> has to be there.

    Furthermore, in the usual case when you have components inside the navigator you normally need to pass them the page stack as well to push or pop from those. Again, there you can use whatever prop name you want so <component :pages="pages"> and receiving in the component with props: ['pages'] also works. In any case you’re always mutating that array that you pass to the navigator, that’s the important part. That’s why in the examples we usually keep the :page-stack and pageStack naming everywhere but maybe that was confusing to you?

    I hope I could shed some light. Here is the tutorial where you can get some more info if you didn’t check that yet. And feel free to ask anything else, naturally :smiley:



  • @misterjunio probably just lack of sleep :sleeping: on my part. I didn’t ask, but I’m curious as to why we need the “navigator” at all (is it being “watched”?). It seems that the default Vue instance makes use of “vue-onsen”. Theoretically couldn’t (¿shouldn’t?) we be able to mutate the array whenever/wherever/however?

    I suppose it “gets confusing” when I wish to make major contextual leaps in the interface. For example, I’d like to be able to click on a list item and have it take me to a new page with a wholly new toolbar, etc. One would think you’d just “import” the relevant Vue template (or page) and “@click” push it onto the “global” pageStack. Perhaps I’m simply going about it incorrectly or completely misunderstanding the implementation. :confused:


  • Onsen UI

    @humblecoder the best person to clarify is @Fran-Diox as it’s his implementation but in short yes, the pageStack is being watched. You need the navigator element to get access to its events and for the back button to work, for example.

    What you described - importing a component and pushing it - is indeed how it works, that’s exactly why you need access to the navigator’s page stack. You can completely change the page stack if you need a whole different context (check this example with splitter+navigator). Otherwise for more complex navigation patterns maybe you should consider using the Vue Router but then you may need their transitions or to create your custom animations.


  • Onsen UI

    @humblecoder The navigator is the component that makes possible having animations, pushing events and having a “stack” of pages (i.e. enabling pop to the last page). It is a simplified router adapted to mobile navigation patterns.

    You can put your pageStack array (name it however you want) in any place as long as you give it to the navigator. After that, it is all a matter of component communication in Vue. You can use events, props or anything as long as you are able to push and pop pages from that array. Component communication in Vue might be a bit complex in some patterns, that’s why they provide Vuex. For example, you can place pageStack in Vuex, making it “global” and accessible from any other component via mutations.

    If you don’t want Vuex, simply provide a way to modify the pageStack in the parts of your app where you need to push/pop pages. In the example you said, you have a page with a list of items and you want to push a new page on item click. Therefore, your page with the list must have access somehow to the pageStack in order to push a new page. There are many ways to do that in Vue:

    <v-ons-navigator :page-stack="myPageStackArray">
      <component
         v-for="page in myPageStackArray"
         :is="page" 
         :pages="myPageStackArray"
      ></component>
    </v-ons-navigator>
    

    Your list page should implement props: ['pages'] (you can change the prop name, it’s your prop). Then, in your list, @click="pages.push(newImportedVueComponentPage)".

    Or, you can also use events instead:

    <v-ons-navigator :page-stack="myPageStackArray">
      <component
         v-for="page in myPageStackArray"
         :is="page" 
         @push="myPageStackArray.push($event)"
      ></component>
    </v-ons-navigator>
    

    This way you don’t need any prop in your list array, simply run @click="$emit('push', newImportedVueComponentPage)" – You can change the event name, it’s your event.

    Another way, if you are ok with using this.$parent (might not be recommended in Vue’s guide), you can simply run this.$parent.pageStack.push(...), since the $parent is the v-ons-navigator and it gets a pageStack prop.

    You could even define a property in Vue’s prototype to make it available in every instance: Vue.prototype.$pageStack = []; and then pass it to the navigator <v-ons-navigator :page-stack="$pageStack">. You can call this.$pageStack.push(...) wherever you want.

    It is all a matter of component communication in Vue, so make sure you understand how it works.


Log in to reply