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.

RFC: $transition$ injectable promise

See original GitHub issue

I’ve been working on the “transition service” idea that’s been tossed around here. See this commit in ui-router-extras: https://github.com/christopherthielen/ui-router-extras/commit/92c4f81208f07ff740399e8d81e218732b9f7469

So far, I have implemented and tested

  • $transition$: an injectable object which contains:
    • the to state/params
    • the from state/params
    • a promise which wraps the $state.transitionTo() promise
  • $transitionStart: a new event, fired in response to $stateChangeStart which exposes the $transition$ object/promise
  • $transitionSuccess and $transitionError Mirrors $stateChangeSuccess/Error, but are broadcasted based on the promise. I’m not sold on these, they seem perhaps unnecessary, but I put them in because it was ridiculously easy to do so.

$transition$

The $transition$ object contains the details of the current transition, to: { state: toState, params: toParams} and from: { state: fromState, params: fromParams } }. It also has promise which is resolved when the promise returned by $state.transitionTo() is resolved.

$transition is injectable as long as the transition is currently in process. This means it can be injected into onEnter/onExit/controller functions.

$transitionStart

The $transitionStart event fires in response to $stateChangeStart. This event exposes $transition to interested parties. Since $transitionStart exposes $transition$, it allows interested parties to listen for transitions, then process them using promises, which was impossible using $stateChangeStart.

benefits

  • Listen for state changes, respond using promises. When listening for $stateChangeStart/Success/Error, there is a separation between the starting event and the terminating event. One also has to listen for both Success and Error events to connect the dots.
  • Inject current transition into code invoked while the transition is pending. Currently, onEnter/Exit/controller don’t know why they are being invoked. For example, the onEnter doesn’t know if the destination state is that specific state, or some substate.
  • ??? other things?
  • Profit!!!

closes

I believe this change would address the following:

https://github.com/angular-ui/ui-router/issues/1169 https://github.com/angular-ui/ui-router/issues/1182 https://github.com/angular-ui/ui-router/issues/1153 https://github.com/angular-ui/ui-router/issues/1151 https://github.com/angular-ui/ui-router/issues/1112 https://github.com/angular-ui/ui-router/issues/1100 https://github.com/angular-ui/ui-router/issues/1085 https://github.com/angular-ui/ui-router/issues/1016 https://github.com/angular-ui/ui-router/issues/575 https://github.com/angular-ui/ui-router/issues/238 https://github.com/angular-ui/ui-router/issues/23

Issue Analytics

  • State:closed
  • Created 9 years ago
  • Comments:20 (12 by maintainers)

github_iconTop GitHub Comments

2reactions
christopherthielencommented, Sep 30, 2015

This is ready to go in 1.0; closing

1reaction
DumboJetcommented, Apr 17, 2015

I am trying to prevent a transition on some occasions like that (and then use $state.go to re-initiate if needed):

$rootScope.$on("$transitionStart", function (event, $transition$) {
           if (isEditing()) {
                      event.preventDefault();
                      //.... Other stuff
           }
}

But event.preventDefault(); seems to do nothing and the transition DOES happen. How can I achieve that? Thanks in advance!

UPDATE: I have changed your lib like so:

              var evt2 = $rootScope.$broadcast("$transitionStart", tData);
              if (evt2.defaultPrevented) evt.preventDefault();

…but then it still calls the callback of the $state.go(...).then() function. 😦 Any idea how to avoid that too?

UPDATE 2: OK. That was the best that I could find so far:

          // Decorate $state.transitionTo.
          $state.transitionTo = function (to, toParams, options) {
            // Create a deferred/promise which can be used earlier than UI-Router's transition promise.
            var deferred = $q.defer();
            // Place the promise in a transition data, and place it on the stack to be used in $stateChangeStart
            var tData = tDataStack[++transitionDepth] = {
              promise: deferred.promise
            };
            // placeholder restoreFn in case transitionTo doesn't reach $stateChangeStart (state not found, etc)
            restoreFnStack[transitionDepth] = function() { };
            // Invoke the real $state.transitionTo
            var tPromise = $state_transitionTo.apply($state, arguments);

              // insert our promise callbacks into the chain.
            if (tData.defaultPrevented) {
                throw '';
            }
            return tPromise.then(transitionSuccess(deferred, tData), transitionFailure(deferred, tData));
          };

          // This event is handled synchronously in transitionTo call stack
        $rootScope.$on("$stateChangeStart", function(evt, toState, toParams, fromState, fromParams) {
                var depth = transitionDepth;
                // To/From is now normalized by ui-router.  Add this information to the transition data object.
                var tData = angular.extend(tDataStack[depth], {
                    to: { state: toState, params: toParams },
                    from: { state: fromState, params: fromParams }
                });

                var restoreFn = decorateInjector(tData);
                restoreFnStack[depth] = restoreFn;
                var evt2 = $rootScope.$broadcast("$transitionStart", tData);
                if (evt2.defaultPrevented) {
                    evt.preventDefault();
                    tDataStack[depth].defaultPrevented = true;
                }
            }
        );

I throw an error to stop the transition. Not good, but does the job… But that prevents the $state.go(...).then() function from being called on successful transitions. 😦 Please inform me if there is another way.

(Note: the code is from transition.js)

Thanks. 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

RFC 9099 - Operational Security Considerations for IPv6 ...
Operational Security Considerations for IPv6 Networks RFC 9099 · 1. Order and Repetition of Extension Headers 2.2. · 2. Hop-by-Hop Options Header 2.2....
Read more >
RouterService - 3.6 - Ember API Documentation
The immediate benefit of the Router service is that you can inject it into components, giving them a friendly way to initiate transitions...
Read more >
Inducible Tertiary Lymphoid Structures: Promise and ... - NCBI
As the SLO develops, LTo cells differentiate into RFC through ... the greatest benefit from iTLS will likely result from injectable or ...
Read more >
IPv4 Exhaustion, IPv6 Transition,
The exhaustion of IPv4 addresses and the transition to IPv6 could result in ... 1980); RFC 791, Internet Protocol: DARPA Internet Program.
Read more >
Understand Open Shortest Path First (OSPF) - Design Guide
The Open Shortest Path First (OSPF) protocol, defined in RFC 2328, ... These networks are injected into OSPF via redistribution.
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