[v2] How to use init false + navigate programmatically

In kitchen sink demo app constructor I added init: false, trying to navigate programmatically after. Page stays blank.

 var app = new Framework7({
  id: 'io.framework7.testapp',
  root: '#app',
  theme: theme,
  init: false,
  data: function () {
    return {
      user: {
        firstName: 'John',
        lastName: 'Doe',
      },
    };
  },
  methods: {
    helloWorld: function () {
      app.dialog.alert('Hello World!');
    },
  },
  routes: routes,
  vi: {
    placementId: 'pltd4o7ibb9rc653x14',
  },
});

console.log('ANYTHING');

// Add main View
var mainView = app.views.create('.view-main', {
	// Enable dynamic Navbar
	dynamicNavbar: true,
});

console.log('REDIRECTING');
//app.views.current
mainView.router.navigate('/buttons/',{
        reloadCurrent: true
});

You need to init the app and navigation will work with app.init()

Okay but the redirect still doesn’t work after app.init();

var mainView = app.views.create(’.view-main’, {

});

This throws an error in the console:

TypeError: i is undefined framework7.js:8252

EDIT: It seems like calling app.views.create on a view that has the “view-init” class might be the problem.

Yes, you shouldn’t do it, you are trying to init view twice

I am able to use init false, and redirect but if pushState is true the redirect falls and this error is thrown in the console. Using F7 2.0.10.

TypeError: documentUrl is undefined - framework7.js:8298

// Init App
var app = new Framework7({
  id: 'io.framework7.testapp',
  root: '#app',
  theme: theme,
  data: function () {
    return {
      user: {
        firstName: 'John',
        lastName: 'Doe',
      },
    };
  },
  methods: {
    helloWorld: function () {
      app.dialog.alert('Hello World!');
    },
  },
  routes: routes,
  vi: {
    placementId: 'pltd4o7ibb9rc653x14',
  },
	
	init: false,
	view: {
		xhrCache: false,
		pushState: true,
		pushStateNoAnimation: true, // Compatible with V2?
		uniqueHistory: true,
  	}
});

app.init();

console.log('app.views.current', app.views.current);

app.views.current.router.navigate('/buttons/');

Did you init the view?

Yes I posted the code above:

app.init();

console.log('app.views.current', app.views.current);

app.views.current.router.navigate('/buttons/');

Page doesn’t change, only throws an error.

How about app.views.create to init the view?

What is in your html and routes?

This is your kitchen sink demo for 2.0.10. The only thing I changed was the code above in app.js. We already established we can’t use app.views.create on a view that has been initialized previously because it throws this error:

TypeError: i is undefined framework7.js:8252

Ok, then it doesn’t make sense to call navigate on home page load. It is better to use initial page route http://framework7.io/docs/view.html#initial-page-route

I commented out the view-init classes in the kitchen sink index.html, then added this to app.js:

// Add main View
mainView = app.views.create('.view-main', {
	url: '/buttons/'
});

app.init();

It doesn’t navigate to the buttons page. Any ideas?

EDIT: It only works when I set pushState to false. I need pushState to so I can navigate directly to the url during testing. I have tried setting it in both app and view and neither works.

Can you post an example of using init: false, with pushState: true, and navigate to a page on init? I am unable to migrate my app from v1 until this is working.

In v1 I simply did:

myApp.init();

mainView = myApp.addView('.view-main', {
});

if (updatesPending){
var t = mainView.router.loadPage({url: 'templates/update.html'});
} else {
var t = mainView.router.loadPage({url: 'templates/login.html'});  
}

#index.html

<html>
  <head>
    <link rel="stylesheet" href="css/framework7.css">
  </head>
  <body>
    <div id="app">
      <div class="view view-main"></div>
    </div>
    <script src="js/framework7.js"></script>
    <script src="js/app.js"></script>
  </body>
</html>

#app.js

var app=new Framework7({
  root:'#app',
  init:false,
  routes:[
    {
      path: '/',
      async(routeTo,routeFrom,resolve,reject){
        resolve({
          url:updatesPending ?
            './pages/about.html' :
            './pages/buttons.html'
        });
      }
    },
    {
      path:'/accordion/',
      url:'./pages/accordion.html'
    }
  ]
});
var view=app.views.create('.view-main',{
  url:'/'
});
/* for testing
var view=app.views.create('.view-main',{
  url:document.location.hash.replace(
        app.params.view.pushStateSeparator,''
      ) || '/'
});
*/
app.init();
view.router.params.pushState=true;
1 Like

So correct me if I’m wrong, but it seems like pushState DOES NOT work at runtime?

It seems like a bug to me.

WORKS

mainView = app.views.create('.view-main', {
    //pushState: true,
    url: '/buttons/'
});

FAILS

mainView = app.views.create('.view-main', {
    pushState: true,
    url: '/buttons/'
});

not a bug

it’s a little bit hard (and long) to explain

it will be better if you answer (in code) :

  • what are you trying to do
  • what is the expescted behavior

My app has 30 possible routes. They can all be accessed directly because some are 5-6 levels deep into the app so i need pushState.

(These are the old routes from v1)

https://www.mysite.com/index.html#!/templates/page-updates.html
https://www.mysite.com/index.html#!/templates/page-login.html
https://www.mysite.com/index.html#!/templates/page-home.html
https://www.mysite.com/index.html#!/templates/page-workorder.html
https://www.mysite.com/index.html#!/templates/page-photos.html
https://www.mysite.com/index.html#!/templates/page-notes.html
https://www.mysite.com/index.html#!/templates/page-forms.html
etc…

EXAMPLE
Enter https://www.mysite.com/index.html#!/workorder/ into the address bar

  1. Init Phonegap, SQLite, database modifications, Firebase, etc…(all asynchronous)
  2. Init F7
  3. In routes.js async method verify permission to route (asynchronous)
  4. Load context data for route (asynchronous)
  5. Load template from file, merge data (synchronous)
  6. Display page

Then when they click a sub-page, e.g. Photos, Notes, Forms I run steps 3-6

#app.js

var userIsLoggedIn = true;
var updatesPending = false;

var routeState=document.location.hash.split('#!')[1];

var state={
  name:'state',
  url:document.location.href.split('#!')[0]
};
history.pushState(state,state.name,state.url);
var app=new Framework7({
  root:'#app',
  init:false,
  routes:[
    {// by logic the url "with this route"
     // should be https://www.mysite.com/index.html "anyway"
      path: '/',
      async(routeTo,routeFrom,resolve,reject){
        resolve({
          url:userIsLoggedIn ?
              updatesPending ?
              './templates/page-updates.html' : // the url is .../index.html
              './templates/page-home.html' :    // the url is .../index.html
              './templates/page-login.html'     // the url is .../index.html
        },{
          once:userIsLoggedIn ?
               updatesPending ? 
               { } :
               {// fire once. 
                // and only if userIsLoggedIn:true and updatesPending:false
                 pageMounted:function(e,page) {
                   page.view.router.params.pushState=true;
                   if(routeState){//if the url has "hash" (route.path)
                     setTimeout(function(){
                       page.view.router.navigate(routeState,{animate:false});
                      // the url is .../index.html#! + (/workorder/ || /photos/)
                     },0);
                   }
                 }
               } :
               { }
        });
      }
    },
    {// the url will be https://www.mysite.com/index.html#!/workorder/
      path:'/workorder/',
      url:'./templates/page-workorder.html'
    },
    {// the url will be https://www.mysite.com/index.html#!/photos/
      path:'/photos/',
      url:'./templates/page-photos.html'
    }
  ]
});
var view=app.views.create('.view-main',{
  url:'/'
});
app.init();

I’m confused about the second parameter you used for resolve(). It has a property named “once” which I don’t see in the Route Options.
https://framework7.io/docs/routes.html#route-options

this is a “working” example

“once” is ok

if you don’t like it
you can change it to “on”

in this case => “pageMounted”
“once” behave like “on” anyway