@uirouter/core
Version:
UI-Router Core: Framework agnostic, State-based routing for JavaScript Single Page Apps
258 lines • 11.5 kB
JavaScript
import { TransitionHookScope, TransitionHookPhase, } from './interface';
import { Transition } from './transition';
import { makeEvent } from './hookRegistry';
import { registerAddCoreResolvables, treeChangesCleanup } from '../hooks/coreResolvables';
import { registerRedirectToHook } from '../hooks/redirectTo';
import { registerOnExitHook, registerOnRetainHook, registerOnEnterHook } from '../hooks/onEnterExitRetain';
import { registerEagerResolvePath, registerLazyResolveState, registerResolveRemaining } from '../hooks/resolve';
import { registerLoadEnteringViews, registerActivateViews } from '../hooks/views';
import { registerUpdateGlobalState } from '../hooks/updateGlobals';
import { registerUpdateUrl } from '../hooks/url';
import { registerLazyLoadHook } from '../hooks/lazyLoad';
import { TransitionEventType } from './transitionEventType';
import { TransitionHook } from './transitionHook';
import { isDefined } from '../common/predicates';
import { removeFrom, values, createProxyFunctions } from '../common/common';
import { val } from '../common/hof';
import { registerIgnoredTransitionHook } from '../hooks/ignoredTransition';
import { registerInvalidTransitionHook } from '../hooks/invalidTransition';
/**
* The default [[Transition]] options.
*
* Include this object when applying custom defaults:
* let reloadOpts = { reload: true, notify: true }
* let options = defaults(theirOpts, customDefaults, defaultOptions);
*/
export var defaultTransOpts = {
location: true,
relative: null,
inherit: false,
notify: true,
reload: false,
supercede: true,
custom: {},
current: function () { return null; },
source: 'unknown',
};
/**
* This class provides services related to Transitions.
*
* - Most importantly, it allows global Transition Hooks to be registered.
* - It allows the default transition error handler to be set.
* - It also has a factory function for creating new [[Transition]] objects, (used internally by the [[StateService]]).
*
* At bootstrap, [[UIRouter]] creates a single instance (singleton) of this class.
*
* This API is located at `router.transitionService` ([[UIRouter.transitionService]])
*/
var TransitionService = /** @class */ (function () {
/** @internal */
function TransitionService(_router) {
/** @internal */
this._transitionCount = 0;
/** The transition hook types, such as `onEnter`, `onStart`, etc */
this._eventTypes = [];
/** @internal The registered transition hooks */
this._registeredHooks = {};
/** The paths on a criteria object */
this._criteriaPaths = {};
this._router = _router;
this.$view = _router.viewService;
this._deregisterHookFns = {};
this._pluginapi = (createProxyFunctions(val(this), {}, val(this), [
'_definePathType',
'_defineEvent',
'_getPathTypes',
'_getEvents',
'getHooks',
]));
this._defineCorePaths();
this._defineCoreEvents();
this._registerCoreTransitionHooks();
_router.globals.successfulTransitions.onEvict(treeChangesCleanup);
}
/**
* Registers a [[TransitionHookFn]], called *while a transition is being constructed*.
*
* Registers a transition lifecycle hook, which is invoked during transition construction.
*
* This low level hook should only be used by plugins.
* This can be a useful time for plugins to add resolves or mutate the transition as needed.
* The Sticky States plugin uses this hook to modify the treechanges.
*
* ### Lifecycle
*
* `onCreate` hooks are invoked *while a transition is being constructed*.
*
* ### Return value
*
* The hook's return value is ignored
*
* @internal
* @param criteria defines which Transitions the Hook should be invoked for.
* @param callback the hook function which will be invoked.
* @param options the registration options
* @returns a function which deregisters the hook.
*/
TransitionService.prototype.onCreate = function (criteria, callback, options) {
return;
};
/** @inheritdoc */
TransitionService.prototype.onBefore = function (criteria, callback, options) {
return;
};
/** @inheritdoc */
TransitionService.prototype.onStart = function (criteria, callback, options) {
return;
};
/** @inheritdoc */
TransitionService.prototype.onExit = function (criteria, callback, options) {
return;
};
/** @inheritdoc */
TransitionService.prototype.onRetain = function (criteria, callback, options) {
return;
};
/** @inheritdoc */
TransitionService.prototype.onEnter = function (criteria, callback, options) {
return;
};
/** @inheritdoc */
TransitionService.prototype.onFinish = function (criteria, callback, options) {
return;
};
/** @inheritdoc */
TransitionService.prototype.onSuccess = function (criteria, callback, options) {
return;
};
/** @inheritdoc */
TransitionService.prototype.onError = function (criteria, callback, options) {
return;
};
/**
* dispose
* @internal
*/
TransitionService.prototype.dispose = function (router) {
values(this._registeredHooks).forEach(function (hooksArray) {
return hooksArray.forEach(function (hook) {
hook._deregistered = true;
removeFrom(hooksArray, hook);
});
});
};
/**
* Creates a new [[Transition]] object
*
* This is a factory function for creating new Transition objects.
* It is used internally by the [[StateService]] and should generally not be called by application code.
*
* @internal
* @param fromPath the path to the current state (the from state)
* @param targetState the target state (destination)
* @returns a Transition
*/
TransitionService.prototype.create = function (fromPath, targetState) {
return new Transition(fromPath, targetState, this._router);
};
/** @internal */
TransitionService.prototype._defineCoreEvents = function () {
var Phase = TransitionHookPhase;
var TH = TransitionHook;
var paths = this._criteriaPaths;
var NORMAL_SORT = false, REVERSE_SORT = true;
var SYNCHRONOUS = true;
this._defineEvent('onCreate', Phase.CREATE, 0, paths.to, NORMAL_SORT, TH.LOG_REJECTED_RESULT, TH.THROW_ERROR, SYNCHRONOUS);
this._defineEvent('onBefore', Phase.BEFORE, 0, paths.to);
this._defineEvent('onStart', Phase.RUN, 0, paths.to);
this._defineEvent('onExit', Phase.RUN, 100, paths.exiting, REVERSE_SORT);
this._defineEvent('onRetain', Phase.RUN, 200, paths.retained);
this._defineEvent('onEnter', Phase.RUN, 300, paths.entering);
this._defineEvent('onFinish', Phase.RUN, 400, paths.to);
this._defineEvent('onSuccess', Phase.SUCCESS, 0, paths.to, NORMAL_SORT, TH.LOG_REJECTED_RESULT, TH.LOG_ERROR, SYNCHRONOUS);
this._defineEvent('onError', Phase.ERROR, 0, paths.to, NORMAL_SORT, TH.LOG_REJECTED_RESULT, TH.LOG_ERROR, SYNCHRONOUS);
};
/** @internal */
TransitionService.prototype._defineCorePaths = function () {
var STATE = TransitionHookScope.STATE, TRANSITION = TransitionHookScope.TRANSITION;
this._definePathType('to', TRANSITION);
this._definePathType('from', TRANSITION);
this._definePathType('exiting', STATE);
this._definePathType('retained', STATE);
this._definePathType('entering', STATE);
};
/** @internal */
TransitionService.prototype._defineEvent = function (name, hookPhase, hookOrder, criteriaMatchPath, reverseSort, getResultHandler, getErrorHandler, synchronous) {
if (reverseSort === void 0) { reverseSort = false; }
if (getResultHandler === void 0) { getResultHandler = TransitionHook.HANDLE_RESULT; }
if (getErrorHandler === void 0) { getErrorHandler = TransitionHook.REJECT_ERROR; }
if (synchronous === void 0) { synchronous = false; }
var eventType = new TransitionEventType(name, hookPhase, hookOrder, criteriaMatchPath, reverseSort, getResultHandler, getErrorHandler, synchronous);
this._eventTypes.push(eventType);
makeEvent(this, this, eventType);
};
/** @internal */
TransitionService.prototype._getEvents = function (phase) {
var transitionHookTypes = isDefined(phase)
? this._eventTypes.filter(function (type) { return type.hookPhase === phase; })
: this._eventTypes.slice();
return transitionHookTypes.sort(function (l, r) {
var cmpByPhase = l.hookPhase - r.hookPhase;
return cmpByPhase === 0 ? l.hookOrder - r.hookOrder : cmpByPhase;
});
};
/**
* Adds a Path to be used as a criterion against a TreeChanges path
*
* For example: the `exiting` path in [[HookMatchCriteria]] is a STATE scoped path.
* It was defined by calling `defineTreeChangesCriterion('exiting', TransitionHookScope.STATE)`
* Each state in the exiting path is checked against the criteria and returned as part of the match.
*
* Another example: the `to` path in [[HookMatchCriteria]] is a TRANSITION scoped path.
* It was defined by calling `defineTreeChangesCriterion('to', TransitionHookScope.TRANSITION)`
* Only the tail of the `to` path is checked against the criteria and returned as part of the match.
*
* @internal
*/
TransitionService.prototype._definePathType = function (name, hookScope) {
this._criteriaPaths[name] = { name: name, scope: hookScope };
};
/** @internal */
// tslint:disable-next-line
TransitionService.prototype._getPathTypes = function () {
return this._criteriaPaths;
};
/** @internal */
TransitionService.prototype.getHooks = function (hookName) {
return this._registeredHooks[hookName];
};
/** @internal */
TransitionService.prototype._registerCoreTransitionHooks = function () {
var fns = this._deregisterHookFns;
fns.addCoreResolves = registerAddCoreResolvables(this);
fns.ignored = registerIgnoredTransitionHook(this);
fns.invalid = registerInvalidTransitionHook(this);
// Wire up redirectTo hook
fns.redirectTo = registerRedirectToHook(this);
// Wire up onExit/Retain/Enter state hooks
fns.onExit = registerOnExitHook(this);
fns.onRetain = registerOnRetainHook(this);
fns.onEnter = registerOnEnterHook(this);
// Wire up Resolve hooks
fns.eagerResolve = registerEagerResolvePath(this);
fns.lazyResolve = registerLazyResolveState(this);
fns.resolveAll = registerResolveRemaining(this);
// Wire up the View management hooks
fns.loadViews = registerLoadEnteringViews(this);
fns.activateViews = registerActivateViews(this);
// Updates global state after a transition
fns.updateGlobals = registerUpdateGlobalState(this);
// After globals.current is updated at priority: 10000
fns.updateUrl = registerUpdateUrl(this);
// Lazy load state trees
fns.lazyLoad = registerLazyLoadHook(this);
};
return TransitionService;
}());
export { TransitionService };
//# sourceMappingURL=transitionService.js.map