question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Feature: Default sub-state for abstract states

See original GitHub issue

As per this discussion: https://github.com/ProLoser/AngularJS-ORM/issues/12

It would be cool if abstract states could have a default sub-state. Lets say project is an abstract state. However, instead of being unable to go directly to it, if you DO go directly to it, you automatically get pushed into a substate (such as project.tasks). This should probably handle either a string or an injectable callback function.

Otherwise I have to do crap like this:

function ProjectController($scope, $state) {
  $scope.$on('$stateChangeSuccess', function(event, toState) {
    if (toState.name === 'project') {
      $state.go('.tasks');
    }
  });
}

If you simply do the check once when the controller loads, then going from project.whatever to project doesn’t re-execute the controller and therefore the check isn’t performed again. If you put this logic earlier (such as in a resolve or onEnter) then the (async?) call to $state.go will restart the entire resolve resolution process since the route never finished loading, which causes an endless loop (unless you add toState checks in, yadda yadda).

Long story short, I think this is an excellent idea and I approve this message.

Issue Analytics

  • State:closed
  • Created 9 years ago
  • Comments:42 (15 by maintainers)

github_iconTop GitHub Comments

1reaction
acollardcommented, Mar 12, 2015

@inca I can’t speak to when this feature will be added. But in the meantime you could use the implementation I described in #1584.

We’ve been using this for a while and it works great.

module.run(['$rootScope', '$state', '$injector', function ($rootScope, $state, $injector) {
    $rootScope.$on('$stateChangeStart',function (event, toState, toParams) {
      var redirect = toState.redirectTo;
      if (redirect) {
        if (angular.isString(redirect)) {
          event.preventDefault();
          $state.go(redirect, toParams);
        }
        else {
          var newState = $injector.invoke(redirect, null, { toState: toState, toParams: toParams });
          if (newState) {
            if (angular.isString(newState)) {
              event.preventDefault();
              $state.go(newState);
            }
            else if (newState.state) {
              event.preventDefault();
              $state.go(newState.state, newState.params);
            }
          }
        }
      }
    });
1reaction
christopherthielencommented, Feb 9, 2015

in #1584 @acollard said:


This is how we handle redirects.

.config(['$stateProvider', '$urlRouterProvider',function($stateProvider, $urlRouterProvider) {
    $stateProvider
        .state('Account.Security', {
          url: '/security',
          redirectTo: 'Account.Security.ChangePassword' // OR
          //redirectTo: function($state){ $state.go('Account.Security.ChangePassword', { id: 'some id' }); }
        });
});

.run(['$rootScope', '$state', function($rootScope, $state){
      $rootScope.$on('$stateChangeStart', function(event, toState) {
        var redirect = toState.redirectTo;
        if (redirect) {
          event.preventDefault();
          if(angular.isFunction(redirect))
              redirect.call($state);
          else
              $state.go(redirect);
        }
      });
    }]);

The redirectTo function could do whatever logic you needed. Ex. get the id for the last item the user was viewing.


@acollard That’s pretty close to what I’m thinking. In ui-router-extras I’ve added a similar option for default substate, using default for the key and { state: “”, params: {} } as the value.

dsr: { 
  default: { state: "Account.Security.ChangePassword", params: { id: 123 } }
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

Set default child of abstract nested state in ui-router
There is a working example. We can use built in features. 1) default is such child state which has empty url: $stateProvider .state('books' ......
Read more >
Guidelines: Statechart Diagram
Generally substates should contain two or more states unless the state machine is abstract and will be refined by sub-classes of the enclosing...
Read more >
State.statedeclaration - UI-Router
An abstract state can never be directly activated. Use an abstract state to provide inherited properties (url, resolve, data, etc) to children states....
Read more >
State Diagram syntax and features - PlantUML
A state can also be composite. You have to define it using the state keywords and brackets. Internal sub-state ...
Read more >
UML State Machine Diagrams - Overview of Graphical Notation
State machine may have an associated behavioral feature (specification) and be the method of this behavioral feature. In this case the state machine ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found