UNPKG

11.8 kBJavaScriptView Raw
1/**
2 * # Legacy state events
3 *
4 * Polyfill implementation of the UI-Router 0.2.x state events.
5 *
6 * The 0.2.x state events are deprecated. We recommend moving to Transition Hooks instead, as they
7 * provide much more flexibility, support async, and provide the context (the Transition, etc) necessary
8 * to implement meaningful application behaviors.
9 *
10 * To enable these state events, include the `stateEvents.js` file in your project, e.g.,
11 * ```
12 * <script src="stateEvents.js"></script>
13 * ```
14 * and also make sure you depend on the `ui.router.state.events` angular module, e.g.,
15 * ```
16 * angular.module("myApplication", ['ui.router', 'ui.router.state.events']
17 * ```
18 *
19 * @publicapi @module ng1_state_events
20 */ /** */
21import { ng as angular } from '../angular';
22/**
23 * An event broadcast on `$rootScope` when the state transition **begins**.
24 *
25 * ### Deprecation warning: use [[TransitionService.onStart]] instead
26 *
27 * You can use `event.preventDefault()`
28 * to prevent the transition from happening and then the transition promise will be
29 * rejected with a `'transition prevented'` value.
30 *
31 * Additional arguments to the event handler are provided:
32 * - `toState`: the Transition Target state
33 * - `toParams`: the Transition Target Params
34 * - `fromState`: the state the transition is coming from
35 * - `fromParams`: the parameters from the state the transition is coming from
36 * - `options`: any Transition Options
37 * - `$transition$`: the [[Transition]]
38 *
39 * #### Example:
40 * ```js
41 * $rootScope.$on('$stateChangeStart', function(event, transition) {
42 * event.preventDefault();
43 * // transitionTo() promise will be rejected with
44 * // a 'transition prevented' error
45 * })
46 * ```
47 *
48 * @event $stateChangeStart
49 * @deprecated
50 */
51export var $stateChangeStart;
52/**
53 * An event broadcast on `$rootScope` if a transition is **cancelled**.
54 *
55 * ### Deprecation warning: use [[TransitionService.onStart]] instead
56 *
57 * Additional arguments to the event handler are provided:
58 * - `toState`: the Transition Target state
59 * - `toParams`: the Transition Target Params
60 * - `fromState`: the state the transition is coming from
61 * - `fromParams`: the parameters from the state the transition is coming from
62 * - `options`: any Transition Options
63 * - `$transition$`: the [[Transition]] that was cancelled
64 *
65 * @event $stateChangeCancel
66 * @deprecated
67 */
68export var $stateChangeCancel;
69/**
70 * An event broadcast on `$rootScope` once the state transition is **complete**.
71 *
72 * ### Deprecation warning: use [[TransitionService.onStart]] and [[Transition.promise]], or [[Transition.onSuccess]]
73 *
74 * Additional arguments to the event handler are provided:
75 * - `toState`: the Transition Target state
76 * - `toParams`: the Transition Target Params
77 * - `fromState`: the state the transition is coming from
78 * - `fromParams`: the parameters from the state the transition is coming from
79 * - `options`: any Transition Options
80 * - `$transition$`: the [[Transition]] that just succeeded
81 *
82 * @event $stateChangeSuccess
83 * @deprecated
84 */
85export var $stateChangeSuccess;
86/**
87 * An event broadcast on `$rootScope` when an **error occurs** during transition.
88 *
89 * ### Deprecation warning: use [[TransitionService.onStart]] and [[Transition.promise]], or [[Transition.onError]]
90 *
91 * It's important to note that if you
92 * have any errors in your resolve functions (javascript errors, non-existent services, etc)
93 * they will not throw traditionally. You must listen for this $stateChangeError event to
94 * catch **ALL** errors.
95 *
96 * Additional arguments to the event handler are provided:
97 * - `toState`: the Transition Target state
98 * - `toParams`: the Transition Target Params
99 * - `fromState`: the state the transition is coming from
100 * - `fromParams`: the parameters from the state the transition is coming from
101 * - `error`: The reason the transition errored.
102 * - `options`: any Transition Options
103 * - `$transition$`: the [[Transition]] that errored
104 *
105 * @event $stateChangeError
106 * @deprecated
107 */
108export var $stateChangeError;
109/**
110 * An event broadcast on `$rootScope` when a requested state **cannot be found** using the provided state name.
111 *
112 * ### Deprecation warning: use [[StateService.onInvalid]] instead
113 *
114 * The event is broadcast allowing any handlers a single chance to deal with the error (usually by
115 * lazy-loading the unfound state). A `TargetState` object is passed to the listener handler,
116 * you can see its properties in the example. You can use `event.preventDefault()` to abort the
117 * transition and the promise returned from `transitionTo()` will be rejected with a
118 * `'transition aborted'` error.
119 *
120 * Additional arguments to the event handler are provided:
121 * - `unfoundState` Unfound State information. Contains: `to, toParams, options` properties.
122 * - `fromState`: the state the transition is coming from
123 * - `fromParams`: the parameters from the state the transition is coming from
124 * - `options`: any Transition Options
125 *
126 * #### Example:
127 * ```js
128 * // somewhere, assume lazy.state has not been defined
129 * $state.go("lazy.state", { a: 1, b: 2 }, { inherit: false });
130 *
131 * // somewhere else
132 * $scope.$on('$stateNotFound', function(event, transition) {
133 * function(event, unfoundState, fromState, fromParams){
134 * console.log(unfoundState.to); // "lazy.state"
135 * console.log(unfoundState.toParams); // {a:1, b:2}
136 * console.log(unfoundState.options); // {inherit:false} + default options
137 * });
138 * ```
139 *
140 * @event $stateNotFound
141 * @deprecated
142 */
143export var $stateNotFound;
144(function () {
145 var isFunction = angular.isFunction, isString = angular.isString;
146 function applyPairs(memo, keyValTuple) {
147 var key, value;
148 if (Array.isArray(keyValTuple))
149 key = keyValTuple[0], value = keyValTuple[1];
150 if (!isString(key))
151 throw new Error('invalid parameters to applyPairs');
152 memo[key] = value;
153 return memo;
154 }
155 function stateChangeStartHandler($transition$) {
156 if (!$transition$.options().notify || !$transition$.valid() || $transition$.ignored())
157 return;
158 var $injector = $transition$.injector();
159 var $stateEvents = $injector.get('$stateEvents');
160 var $rootScope = $injector.get('$rootScope');
161 var $state = $injector.get('$state');
162 var $urlRouter = $injector.get('$urlRouter');
163 var enabledEvents = $stateEvents.provider.enabled();
164 var toParams = $transition$.params('to');
165 var fromParams = $transition$.params('from');
166 if (enabledEvents.$stateChangeSuccess) {
167 var startEvent = $rootScope.$broadcast('$stateChangeStart', $transition$.to(), toParams, $transition$.from(), fromParams, $transition$.options(), $transition$);
168 if (startEvent.defaultPrevented) {
169 if (enabledEvents.$stateChangeCancel) {
170 $rootScope.$broadcast('$stateChangeCancel', $transition$.to(), toParams, $transition$.from(), fromParams, $transition$.options(), $transition$);
171 }
172 // Don't update and resync url if there's been a new transition started. see issue #2238, #600
173 if ($state.transition == null)
174 $urlRouter.update();
175 return false;
176 }
177 // right after global state is updated
178 var successOpts = { priority: 9999 };
179 $transition$.onSuccess({}, function () {
180 $rootScope.$broadcast('$stateChangeSuccess', $transition$.to(), toParams, $transition$.from(), fromParams, $transition$.options(), $transition$);
181 }, successOpts);
182 }
183 if (enabledEvents.$stateChangeError) {
184 $transition$.promise['catch'](function (error) {
185 if (error && (error.type === 2 /* RejectType.SUPERSEDED */ || error.type === 3) /* RejectType.ABORTED */)
186 return;
187 var evt = $rootScope.$broadcast('$stateChangeError', $transition$.to(), toParams, $transition$.from(), fromParams, error, $transition$.options(), $transition$);
188 if (!evt.defaultPrevented) {
189 $urlRouter.update();
190 }
191 });
192 }
193 }
194 stateNotFoundHandler.$inject = ['$to$', '$from$', '$state', '$rootScope', '$urlRouter'];
195 function stateNotFoundHandler($to$, $from$, injector) {
196 var $state = injector.get('$state');
197 var $rootScope = injector.get('$rootScope');
198 var $urlRouter = injector.get('$urlRouter');
199 var redirect = { to: $to$.identifier(), toParams: $to$.params(), options: $to$.options() };
200 var e = $rootScope.$broadcast('$stateNotFound', redirect, $from$.state(), $from$.params());
201 if (e.defaultPrevented || e.retry)
202 $urlRouter.update();
203 function redirectFn() {
204 return $state.target(redirect.to, redirect.toParams, redirect.options);
205 }
206 if (e.defaultPrevented) {
207 return false;
208 }
209 else if (e.retry || !!$state.get(redirect.to)) {
210 return e.retry && isFunction(e.retry.then) ? e.retry.then(redirectFn) : redirectFn();
211 }
212 }
213 $StateEventsProvider.$inject = ['$stateProvider'];
214 function $StateEventsProvider($stateProvider) {
215 $StateEventsProvider.prototype.instance = this;
216 var runtime = false;
217 var allEvents = ['$stateChangeStart', '$stateNotFound', '$stateChangeSuccess', '$stateChangeError'];
218 var enabledStateEvents = allEvents.map(function (e) { return [e, true]; }).reduce(applyPairs, {});
219 function assertNotRuntime() {
220 if (runtime)
221 throw new Error('Cannot enable events at runtime (use $stateEventsProvider');
222 }
223 /**
224 * Enables the deprecated UI-Router 0.2.x State Events
225 * [ '$stateChangeStart', '$stateNotFound', '$stateChangeSuccess', '$stateChangeError' ]
226 */
227 this.enable = function () {
228 var events = [];
229 for (var _i = 0; _i < arguments.length; _i++) {
230 events[_i] = arguments[_i];
231 }
232 assertNotRuntime();
233 if (!events || !events.length)
234 events = allEvents;
235 events.forEach(function (event) { return (enabledStateEvents[event] = true); });
236 };
237 /**
238 * Disables the deprecated UI-Router 0.2.x State Events
239 * [ '$stateChangeStart', '$stateNotFound', '$stateChangeSuccess', '$stateChangeError' ]
240 */
241 this.disable = function () {
242 var events = [];
243 for (var _i = 0; _i < arguments.length; _i++) {
244 events[_i] = arguments[_i];
245 }
246 assertNotRuntime();
247 if (!events || !events.length)
248 events = allEvents;
249 events.forEach(function (event) { return delete enabledStateEvents[event]; });
250 };
251 this.enabled = function () { return enabledStateEvents; };
252 this.$get = $get;
253 $get.$inject = ['$transitions'];
254 function $get($transitions) {
255 runtime = true;
256 if (enabledStateEvents['$stateNotFound'])
257 $stateProvider.onInvalid(stateNotFoundHandler);
258 if (enabledStateEvents.$stateChangeStart)
259 $transitions.onBefore({}, stateChangeStartHandler, { priority: 1000 });
260 return {
261 provider: $StateEventsProvider.prototype.instance,
262 };
263 }
264 }
265 angular
266 .module('ui.router.state.events', ['ui.router.state'])
267 .provider('$stateEvents', $StateEventsProvider)
268 .run([
269 '$stateEvents',
270 // eslint-disable-next-line @typescript-eslint/no-unused-vars
271 function ($stateEvents) {
272 /* Invokes $get() */
273 },
274 ]);
275})();
276//# sourceMappingURL=stateEvents.js.map
\No newline at end of file