[SOLVED] [V2] Stacked Pages


#4

First its not my template, it belongs to Pvtallulah around the forum, you can ask him spesific questions

What you mean screens are loaded into the DOM again and again ?? I also use that template , I didnt knew about it, how you follow it ? Is that means after a while applications getting started slowly because too many pages loaded ?


#5

Thanks for the reply, rastek.

I mean that the Init event of the pages is triggered every time they show up when it should fire only once.

In the attached image you can see that the pages are loaded repeatedly in the DOM. The result sought is like the one described in the example flow above.


#6

Istn it expected that Init event of the pages is triggered every time they show up ? meanwhile where is that init code ? for example I dont use init for a component in vue, I just use created/computed if I need, maybe I am missing something here.

btw, right side is you UI ? or is it some kind of develop screen ? how you open it ?

is that repeated list shows they are all loaded ? or it just ordered list of pages opened one after another ? like some logging


#7

Here you can see the Page Events: http://framework7.io/vue/page.html

It’s an navigator extensión (Mozilla in my case) called “Vue.js devtools”.

The list shows all the pages that have been loaded on the stack. The behavior sought is that they do not repeat themselves and remain on the stack once they have been loaded.


#8

Hi @fabricio,
So you want stacked pages, but instead of creating a new instance of a page, load the page that’s is already created right?
I dont know how to achive that, will try it.
Just curious, why you need stacked pages?


#9

Exactly, @pvtallulah.

I need the stacked pages to maintain their status in case the user navigates to another page (from the side menu) and at some point decides to return.

Thank you for your reply and for having shared the template code “base-vue-f7v2-template”.

I am available for any additional information you need.


#10

@fabricio i try to make it work as you ask, and i couldn’t, the pages keep stacking on DOM.
i even try to prevent route but couldn’t succeed. even i call reject() but f7 continues to the route, so maybe reject() dosnt work?

router reject method:

...
  {
    path: '/about/',
    component: AboutPage,
    async(routeTo, routeFrom, resolve, reject) {
      if (this.history.indexOf(routeTo.path) >= 0) {
        console.log('page exist on stack')
        reject()
      } else {
        console.log('page DONT exist on stack')
        resolve()
      }
    }
  },
...

Set params on f7 init gives an error:

...
  framework7: {
    id: 'com.base.app', // App bundle ID
    name: 'BaseApp', // App name
    theme: 'ios', // MD theme
    // App routes
    routes: Routes,
    view: {
      stackPages: true,
      uniqueHistory: true,
      // If commented pushState apps works fine, but pages keep stacking
      pushState: true
    }
  },
...

[Vue warn]: Duplicate keys detected: ‘1529714183634’. This may cause an update error.

But if i set it in mounted ()
apps load with no error;

  mounted () {
    this.$f7.view.main.params.stackPages = true
    this.$f7.view.main.params.uniqueHistory = true
    this.$f7.view.main.params.pushState = true
  },

But pages keep stacking.

I dont know if this is how f7 is design to work or im doing something wrong. Since i never used Stacked Pages.
Maybe @nolimits4web can clarify the issue.


#11

Thank you very much @pvtallulah. Honestly, I had not thought of trying that alternative.
I was working on his example and it occurred to me to do something like this:
{
path: ‘/about/’,
name: ‘page-about’,
async(routeTo, routeFrom, resolve, reject) {
if (this.history.indexOf(routeTo.path) >= 0) {
console.log(‘page exist on stack’);
// Navigate to page by pageName
//resolve({ pageName: ‘page-about’ });
} else {
console.log(‘page DONT exist on stack’)
resolve({component: AboutPage});
}
}

The problem is that I do not know how to navigate via pageName. Will this be possible? Can you think of a way to solve it?

It would be important to have the opinion of @nolimits4web , meanwhile I will continue trying.


#12

If you enable stackPages: true for View, it will keep pages in DOM while you navigate forward.

But if you need to reuse all pages and load them all at once, then it requires different layout and all pages must be loaded to view initially and not loaded by router:

<f7-view :stackPages="true">
  <f7-page name="home" stacked>...</f7-page>
  <f7-page name="about" stacked>...</f7-page>
  <f7-page name="other" stacked>...</f7-page>
</f7-view>

And in routes you need to specify them by page name:

{
  path: '/about/',
  pageName: 'about',
},

#13

Thank you very much Vladimir, I have been able to solve the issue with the indicated Layout.

Take this opportunity to ask a question, can I keep the following structure in the page components?

user-list.vue

Summary
<template>
  <f7-page name="user-list" stacked>
    <f7-navbar>This text will be hidden
      <f7-nav-left>
        <f7-link icon-if-ios="f7:menu" icon-if-md="material:menu" panel-open="left"></f7-link>
      </f7-nav-left>
      <f7-nav-title>User list</f7-nav-title>
    </f7-navbar>
    <div class="list media-list" v-if="users.length != 0">
      <ul>
        <li v-for="user in users">
          <a :href="user | toUrl" class="item-link item-content">
            <div class="item-media lazy-blur-parent">
              <img
              :data-src="user.picture.large"
              :src="user.picture.thumbnail"
              class="lazy lazy-blur"
              width="80"/>
            </div>
            <div class="item-inner">
                <div class="item-title-row">
                  <div class="item-title">{{user.name.first}} {{user.name.last}}</div>
                </div>
                <div class="item-subtitle">{{user.gender}}</div>
                <div class="item-text">{{user.location.street}} - {{user.location.city}} - {{user.location.state}}</div>
            </div>
          </a>
        </li>
      </ul>
    </div>
  </f7-page>
</template>
<script>
  export default {
    data () {
      let users = [];
      return {
        users
      };
    },
    filters: {
      toUrl(user)
      {
        return '/user-list/user/' + user.gender + '/'
      }
    },
    methods: {
      getUsersList () {
        const self = this;
        self.$root.$f7.dialog.progress();
        self.$request.get('https://randomuser.me/api/?results=15',
          function (data, status, xhr) {
            self.users = data.results;
            self.$root.$f7.dialog.close();
            setTimeout(function(){
              self.$root.$f7.lazy.create('img.lazy');
            },1000)
          },
          function (xhr, status) {
            console.log('Error: '+ JSON.stringify(xhr));
            self.$root.$f7.dialog.close();
          },
          "json");
      },
    },
    on:
    {
      pageInit (event, pageData) {
        this.getUsersList();
      }
    }
  };
</script>
<style lang="scss" scoped>
  .md .list
  {
    margin-top: 0px;
  }
  .md .media-list .item-media
  {
    height: 80px;
    margin-top: 14px;
    margin-bottom: 14px;
    padding-top: 0px;
    padding-bottom: 0px;
  }
</style>

app.vue

Summary
<template>
  <!-- App -->
  <div id="app">

    <!-- Statusbar -->
    <f7-statusbar></f7-statusbar>

    <!-- Left Panel -->
    <f7-panel left reveal theme-dark>
      <f7-view url="/panel-left/"></f7-view>
    </f7-panel>

    <!-- Main View -->
    <f7-view id="main-view" :stackPages="true" main>
      <page-home>
      </page-home>
      <page-about>
      </page-about>
      <page-other>
      </page-other>
      <page-user-list>
      </page-user-list>
    </f7-view>

  </div>
</template>

<script>
import Vue from 'vue';

import HomePage from './pages/home.vue';
import AboutPage from './pages/about.vue';
import OtherPage from './pages/other.vue';
import UserList from './pages/user-list.vue';

Vue.component('page-home', HomePage);
Vue.component('page-about', AboutPage);
Vue.component('page-other', OtherPage);
Vue.component('page-user-list', UserList);

export default {
    components:
    {
      HomePage, AboutPage, OtherPage,UserList
    },
    data () {
    }
  }
</script>

This way the page events don’t fire and I want to avoid putting all the code in route.js

I was trying in many ways but I have not succeeded. Is there any way to solve it?

Thank you very much, your work is fantastic.


#14

Just use Vue’s mounted hook instead of pageInit event in this case


#15

The mounted event is launched correctly but I don’t need it to be launched at the beginning of the App (when the component is loaded in the DOM). I need launch it when the screen is first shown.

On the other hand, what happens with the other page events such as “pageBeforeIn”. I can not subscribe to them within the page component?

Thank you very much for your time Vladimir.


#16

you can use any vue lifecycle event. just use the events in any page you want


#17

Use them as events:

<f7-page @page:beforein="onPageBeforeIn">...</f7-page>
{
  methods: {
    onPageBeforeIn() {
      ...
    }
  }
}

#18

It works like a charm.

Thank you very much Vladimir, you are the best!


#19

Fabricio is that solve your problem ? My vue + v2 app beside slowness and most of the time screen freezes after a while, I am investigating it maybe its the reason you wrote in the post.


How to use stacked pages?
#20

Yes, @rastek. This issue has been fixed.


#21

fabricio, how did you end up solving the issue of navigating via pageName? I see that you attempted to use resolve({ pageName: ‘page-about’ }); via async, I tried it too but it didn’t keep the scroll position (besides, surely it’s not necessary to use async just to nagivate by page name??)


#22

Hello! It is not necessary to use async to call the pages via “pageName”.
You need to change the layoud of the project and the routing as indicated by Vladimir:


#23

Thank you for replying! So what you mean is using that layout, and then doing routing the normal url? e.g. router.navigator("/about/")