Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to replace/overwrite a ui-router state definition? (default state being "customized" by another module)

Is it possible to simply replace a state definition with a new one?

The use case I have is that one module defines the state, and I'd like to be able to replace that state definition from a different module. Basically the initial definition is a "default" definition, and I'd like to have the possibility to customize the state from a different module.

I realize that doing this at config time could result in a race condition on which module defines it first. I looked into the possibility of doing it at run-time, but couldn't get it working.

I can accomplish what I want by creating entirely new states, but I would like to use the same URL from the original state.

Edit:

To further clarify what I am trying to accomplish... Please consider the following code:

angular.module('module1', ['ui.router'])
.config(['$stateProvider', function($stateProvider){
    $stateProvider
        .state('root', {
            url: '',
            abstract: true,
            template: '<div class="layout sub" ui-view="sub"></div>'
        })
        .state('root.sub1', {
            url: '/sub1',
            views: {
                'sub@root': {
                    template: '<p>Default sub state 1</p>'
                }
            }
        });
}]);

angular.module('module2', ['ui.router'])
.config(['$stateProvider', function($stateProvider){
    $stateProvider
        .state('root.sub1', {
            url: '/sub2',
            views: {
                'sub@root': {
                    template: '<p>Customized sub state 1</p>'
                }
            }
        });
}]);

Which of course gives "Error: State 'root.sub1'' is already defined"

like image 539
plong0 Avatar asked Aug 26 '15 19:08

plong0


People also ask

What is UI in Router?

UI-Router is the defacto standard for routing in AngularJS. Influenced by the core angular router $route and the Ember Router, UI-Router has become the standard choice for routing non-trivial apps in AngularJS (1. x).

How ui sref works?

A ui-sref is a directive, and behaves similar to an html href . Instead of referencing a url like an href , it references a state. The ui-sref directive automatically builds a href attribute for you ( <a href=...> </a> ) based on your state's url.

What is UI sref active in AngularJS?

A single uiSrefActive can be used for multiple uiSref links. This can be used to create (for example) a drop down navigation menu, where the menui is highlighted if any of its inner links are active. The uiSrefActive should be placed on an ancestor element of the uiSref list.


3 Answers

Ok, so as I was putting together a plnkr demo of what I tried next, I found that it actually works if you use $state.get and update it.

angular.module('module2', ['ui.router'])
.run(['$state', function($state){
  var state = $state.get('root.sub1');
  if(state && state.views && state.views['sub@root']){
    state.views['sub@root'].template = '<p>Customized sub state 1</p>';
  }
}]);

Plnkr: http://plnkr.co/edit/xLdCgjeM33z2Hf5CHfZR

Edit:

I figured out that it wasn't working in my app because I didn't define the view I wanted to override in the original state.

Example (doesn't work):

angular.module('module1', ['ui.router'])
.config(['$stateProvider', function($stateProvider){
    $stateProvider
        .state('root', {
            url: '',
            abstract: true,
            template: '<div class="layout sub" ui-view="sub"></div>'
        })
        .state('root.sub1', {
            url: '/sub1',
            views: {
            }
        });
}]);

angular.module('module2', ['ui.router'])
.run(['$state', function($state){
    var state = $state.get('root.sub1');
    if(state && state.views){
        state.views['sub@root'] = { template: '<p>Customized sub state 1</p>' };
    }
}]);
like image 56
plong0 Avatar answered Dec 05 '22 18:12

plong0


it seems like there is no way to overwrite it for < v1, unless you need to rewrite the decorator for the stateProvider.

for v1, there is a new method deregister for that purpose https://github.com/angular-ui/ui-router/commit/44579ecbafe15ad587dc341ba4a80af78b62bdaa

I tried using $state.get(view) and overwrite the value, but the controller and template are not registered properly because the built-in decorator is using stateBuilder property to generate the controller and template.

check https://github.com/angular-ui/ui-router/blob/0.3.2/src/state.js

like image 28
Kang Ming Chua Avatar answered Dec 05 '22 18:12

Kang Ming Chua


The best approach I've found to solving this is to:

  1. Create a 'root' controller (ie. a state that loads prior to other states)

.state('root' , { url: ':/root_path', controller: 'rootController' ..other stuff here })

  1. In rootController, you decide what to do with the route:

db.call(pull-root-key-from-db) .then(function(root_response) { if (root_response.type == "user") { $state.go("user.dashboard") })

Sorry for formatting, I'm mobile :)

like image 28
James Gentes Avatar answered Dec 05 '22 16:12

James Gentes