Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

load module on demand #22

Open
hippich opened this issue Oct 20, 2015 · 2 comments
Open

load module on demand #22

hippich opened this issue Oct 20, 2015 · 2 comments

Comments

@hippich
Copy link
Contributor

hippich commented Oct 20, 2015

I feel like this should be possible to do, but could not find exact steps to make it happen. What I want to do - I want to split my application into separate modules, let's say base, dashboard, profile. states for base module will be loaded upfront, but dashboard and profile to be loaded only when /dashboard/* and /profile/* state is hit. I see that I can use 'canEnter' to do loading, but StateMan emits not-found whenever I entering substate straight without going to /dashboard or /profile first...

Any ideas how this could be done using stateman as is?

@leeluolee
Copy link
Owner

In your case, sub states of dashboard or profile are all dynamic loaded , right?

The snippet below may works, see routing param for more detail

var stateman = new StateMan();

var loadPage  = function(path){
  return new Promise(function(resolve, reject){
    setTimeout(function(){
        console.log('page '+path + ' has loaded')
        resolve('content for ' + path)
    }, 1000)
  })
}

stateman.state({

  "app": {url: ''},
  "app.dashboard": {
    // named pattern
    loaded: {},
    url: '/dashboard/:path(.*)',
    canEnter: function(option){
      var path = option.param.path;
      var loaded = this.loaded;
      if(loaded[path]){
        return true;
      }else{
        console.log('page is loading')
        return loadPage(path).then(function(content){
          loaded[path] = content
          return true;
        }).catch(function(){
          console.log('load error')
        })
      }

    },
    canLeave: function(){
      // forbid leave here
    },
    enter: function(option){
      var path = option.param.path;
      console.log('enter app.dashboard content is:' + this.loaded[path])
    }
  },
  "app.profile": {
    // unamed pattern
    url: '/profile/(.*)',
    canEnter: function(option){
      var path = option.param[0];
      console.log('app.profile with ' + path)
    }
  }



}).on('notfound', function(){
  this.go('app')
}).start()

__ or you want to create sub state dynamically that according to the url ? __

@hippich
Copy link
Contributor Author

hippich commented Oct 21, 2015

Thanks! Yeah, this is how I started but I wanted to create routes dynamically after specific module is loaded (I am using require.js). This is what end up last night - https://github.com/hippich/backbone-ractivejs-requirejs-boilerplate/blob/master/js/controller.js#L27

Basically, in notfound event handler I check if this path is one of "loadable" using regex and if so - load it and then navigate to the same path again.

Another approach I tried, but failed:

stateman.state('dashboard', {
  url: '/dashboard(.*)',
  canEnter: loadModule('xxx')
});

and in module 'xxx' define new states somewhat like this:

stateman.state('dashboard.index', {
  url: '/dashboard/index',
  ....
});

It in fact loaded module 'xxx' but since dashboard state matched /dashboard/index, it never fired enter for dashboard.index state.

This could be solved, if I would be allowed to delete states, is it an option? Since I would certainly prefer that instead of handling routing in notfound event handler.

leeluolee added a commit that referenced this issue Nov 24, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants