christopherthielen / ui-router-extras

THIS PROJECT IS NO LONGER MAINTAINED -- Extras for UI-Router for AngularJS. Sticky States (a.k.a. parallel states), Deep State Redirect (for tab-like navigation), Future States (async state definition)
http://christopherthielen.github.io/ui-router-extras/
MIT License
915 stars 211 forks source link

End of Life, UI-Router v1.x and $previousState #371

Open majew7 opened 7 years ago

majew7 commented 7 years ago

Hello @christopherthielen,

You just added the END OF LIFE NOTICE (commit 96025cdbec9), explaining that "UI-Router 1.0 now includes all the features of ui-router-extras out of the box".

I'd like to move off ui-router-extras and explore using ui-router v1.0. However we are using $previousState of the Previous State Feature Is there an equivalent in ui-router v1.0? I don't see it; perhaps I'm missing it.

Question) Has $previousState been ported over to ui-router yet? Or will it not be ported? In your README.md, I didn't see an explicit mention.

Any feedback would be helpful. Thanks!

mathiasmoeller commented 7 years ago

@majew7 I am facing the same problem. Did you find anything in the new implementation yet?

majew7 commented 7 years ago

Hi @mathiasmoeller, I've moved on from the project, so I'm having difficulty recalling everything, but I think I concluded that this Previous State Feature wasn't unique, and thus I just implemented a new service that actually worked better for our domain. I think I tied it together with the ui-router event $stateChangeStart.

majew7 commented 7 years ago

Would still love to hear @christopherthielen chime in though.

dmeagor commented 7 years ago

Could anyone post some code for a noob to deal with this missing previousState feature?

christopherthielen commented 7 years ago

I ported the code to use 1.0 TransitionService and converted it to typescript:

import { StateOrName, StateDeclaration, Transition, TransitionOptions, TransitionService, StateService } from '@uirouter/core';

import * as angular from 'angular';
import IInjectorService = angular.auto.IInjectorService;

interface PreviousMemo {
  state: StateDeclaration;
  params: object;
}

const ngModule = angular.module('ct.ui.router.extras.previous', ['ct.ui.router.extras.core', 'ct.ui.router.extras.transition']);

function PreviousStateService($state: StateService, $q: angular.IQService, $transitions: TransitionService) {
  let previous: PreviousMemo = null;
  let lastPrevious: PreviousMemo = null;
  const memos: { [key: string]: PreviousMemo } = {};

  $transitions.onStart({}, function ($transition$: Transition) {
    const fromState = $transition$.from().$$state();

    function commit() {
      lastPrevious = null;
    }

    function revert() {
      previous = lastPrevious;
    }

    if (fromState) {
      lastPrevious = previous;
      previous = {
        state: $transition$.from(),
        params: $transition$.params('from'),
      };

      $transition$.promise.then(commit)['catch'](revert);
    }
  });

  const $previousState = {
    get: function (memoName: string) {
      return memoName ? memos[memoName] : previous;
    },
    set: function (memoName: string, previousState: StateOrName, previousParams: object) {
      memos[memoName] = { state: $state.get(previousState), params: previousParams };
    },
    go: function (memoName: string, options: TransitionOptions) {
      const to = $previousState.get(memoName);
      if (!to) {
        return $q.reject(new Error('no previous state ' + (memoName ? 'for memo: ' + memoName : '')));
      }
      return $state.go(to.state, to.params, options);
    },
    memo: function (memoName: string, defaultStateName: string, defaultStateParams: object) {
      memos[memoName] = previous || { state: $state.get(defaultStateName), params: defaultStateParams };
    },
    forget: function (memoName: string) {
      if (memoName) {
        delete memos[memoName];
      } else {
        previous = undefined;
      }
    }
  };

  return $previousState;
}
PreviousStateService.$inject = ['$state', '$q', '$transitions'];

ngModule.service('$previousState', PreviousStateService);

ngModule.run(['$injector', function ($injector: IInjectorService) {
  // Inject $previousState so it initializes and registers hooks
  $injector.get('$previousState');
}]);
dmeagor commented 7 years ago

Thanks a lot for that Chris, very much appreciated!

lukebooroo commented 7 years ago

Worked great, just had one issue, $transition$.params() gets the 'to' params rather than 'from'. Thanks!

christopherthielen commented 7 years ago

just had one issue

Good catch! Updated the code

logan-jobzmall commented 6 years ago

@christopherthielen - Since I don't have typescript in my project, is there anyway we can get this on NPM use this similarly to the plugins you have developed for sticky states, etc? Sticky states seems to be hairy without know the previous state.

divyasreekandalam25 commented 6 years ago

@christopherthielen - I am using angular 1.6.9 ui-router:1.0.15. Could you kindly suggest me how to use Previous state without using ui-router-extras. Thank you in advance

christopherthielen commented 6 years ago

@logan-jobzmall I'm not interested in maintaining the previous state implementation, because I don't think it's very useful. I've transpiled it for you to javascript. If you want to publish this to NPM yourself, feel free!

https://gist.github.com/christopherthielen/babf6deebcd9a183dfecd37a03f75199