@angular-wave/angular.ts 0.0.30 → 0.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/angular-ts.esm.js +1 -1
- package/dist/angular-ts.umd.js +1 -1
- package/index.html +5 -14
- package/package.json +1 -1
- package/src/core/compile.js +5 -4
- package/src/core/location.js +1 -1
- package/src/core/parser/parse.js +1 -2
- package/src/core/root-scope.js +49 -99
- package/src/directive/events.js +2 -1
- package/src/directive/model.js +4 -2
- package/src/router/directives/state-directives.js +33 -18
- package/src/router/directives/view-directive.js +1 -2
- package/src/router/globals.js +2 -0
- package/src/router/hooks/url.js +4 -4
- package/src/router/index.js +23 -27
- package/src/router/injectables.js +1 -52
- package/src/router/services.js +6 -84
- package/src/router/state/state-builder.js +7 -6
- package/src/router/state/state-queue-manager.js +2 -1
- package/src/router/state/state-registry.js +39 -21
- package/src/router/state/state-service.js +173 -6
- package/src/router/state/views.js +46 -2
- package/src/router/transition/reject-factory.js +0 -8
- package/src/router/transition/transition-service.js +43 -1
- package/src/router/url/url-config.js +32 -1
- package/src/router/url/url-rule.js +4 -4
- package/src/router/url/url-service.js +161 -14
- package/src/router/view/view.js +7 -51
- package/src/services/http.js +1 -1
- package/src/shared/common.js +1 -1
- package/src/shared/strings.js +7 -2
- package/test/core/compile.spec.js +2 -2
- package/test/core/scope.spec.js +2 -37
- package/test/router/services.spec.js +14 -31
- package/test/router/state-directives.spec.js +2 -2
- package/test/router/state-filter.spec.js +0 -2
- package/test/router/state.spec.js +4 -4
- package/test/router/template-factory.spec.js +19 -10
- package/test/router/{url-matcher-factory.spec.js → url-service.spec.js} +126 -132
- package/test/router/view-directive.spec.js +9 -9
- package/test/router/view-hook.spec.js +10 -10
- package/test/router/view.spec.js +4 -11
- package/types/router/core/params/interface.d.ts +2 -2
- package/types/router/core/url/urlMatcherFactory.d.ts +1 -1
- package/legacy/angular-animate.js +0 -4272
- package/legacy/angular-aria.js +0 -426
- package/legacy/angular-message-format.js +0 -1072
- package/legacy/angular-messages.js +0 -829
- package/legacy/angular-route.js +0 -1266
- package/legacy/angular-sanitize.js +0 -891
- package/legacy/angular.js +0 -36600
- package/src/router/router.js +0 -125
- package/src/router/url/url-matcher-factory.js +0 -76
- package/src/router/url/url-router.js +0 -101
- package/test/original-test.html +0 -33
|
@@ -259,56 +259,5 @@ let $urlServiceProvider;
|
|
|
259
259
|
* ##### Note: This service can also be injected during the config phase as [[$urlServiceProvider]].
|
|
260
260
|
*/
|
|
261
261
|
let $urlService;
|
|
262
|
-
|
|
263
|
-
* The URL Router Provider
|
|
264
|
-
*
|
|
265
|
-
* ### Deprecation warning: This object is now considered internal. Use [[$urlServiceProvider]] instead.
|
|
266
|
-
*
|
|
267
|
-
* The [[UrlRouter]] singleton as a **Provider Object** (injectable during config time).
|
|
268
|
-
*
|
|
269
|
-
* #### Note: This object is also exposed as [[$urlRouter]] for injection during runtime.
|
|
270
|
-
*
|
|
271
|
-
* @deprecated
|
|
272
|
-
*/
|
|
273
|
-
let $urlRouterProvider;
|
|
274
|
-
/**
|
|
275
|
-
* The Url Router
|
|
276
|
-
*
|
|
277
|
-
* ### Deprecation warning: This object is now considered internal. Use [[$urlService]] instead.
|
|
278
|
-
*
|
|
279
|
-
* The [[UrlRouter]] singleton as a **Service Object** (injectable during runtime).
|
|
280
|
-
*
|
|
281
|
-
* #### Note: This object is also exposed as [[$urlRouterProvider]] for injection during angular config time.
|
|
282
|
-
*
|
|
283
|
-
* @deprecated
|
|
284
|
-
*/
|
|
285
|
-
let $urlRouter;
|
|
286
|
-
/**
|
|
287
|
-
* The URL Matcher Factory
|
|
288
|
-
*
|
|
289
|
-
* ### Deprecation warning: This object is now considered internal. Use [[$urlService]] instead.
|
|
290
|
-
*
|
|
291
|
-
* The [[UrlMatcherFactory]] singleton as a **Service Object** (injectable during runtime).
|
|
292
|
-
*
|
|
293
|
-
* This service is used to set url mapping options, define custom parameter types, and create [[UrlMatcher]] objects.
|
|
294
|
-
*
|
|
295
|
-
* #### Note: This object is also exposed as [[$urlMatcherFactoryProvider]] for injection during angular config time.
|
|
296
|
-
*
|
|
297
|
-
* @deprecated
|
|
298
|
-
*/
|
|
299
|
-
let $urlMatcherFactory;
|
|
300
|
-
/**
|
|
301
|
-
* The URL Matcher Factory
|
|
302
|
-
*
|
|
303
|
-
* ### Deprecation warning: This object is now considered internal. Use [[$urlService]] instead.
|
|
304
|
-
*
|
|
305
|
-
* The [[UrlMatcherFactory]] singleton as a **Provider Object** (injectable during config time).
|
|
306
|
-
*
|
|
307
|
-
* This service is used to set url mapping options, define custom parameter types, and create [[UrlMatcher]] objects.
|
|
308
|
-
*
|
|
309
|
-
* #### Note: This object is also exposed as [[$urlMatcherFactory]] for injection during runtime.
|
|
310
|
-
*
|
|
311
|
-
* @deprecated
|
|
312
|
-
*/
|
|
313
|
-
let $urlMatcherFactoryProvider;
|
|
262
|
+
|
|
314
263
|
export {};
|
package/src/router/services.js
CHANGED
|
@@ -9,67 +9,11 @@
|
|
|
9
9
|
* @preferred @publicapi @module ng1
|
|
10
10
|
*/
|
|
11
11
|
import { services } from "./common/coreservices";
|
|
12
|
-
import {
|
|
13
|
-
import { isString } from "../shared/utils";
|
|
12
|
+
import { unnestR } from "../shared/common";
|
|
14
13
|
import { trace } from "./common/trace";
|
|
15
|
-
import { UIRouter } from "./router";
|
|
16
|
-
import { StateProvider } from "./state-provider";
|
|
17
14
|
|
|
18
|
-
|
|
19
|
-
export
|
|
20
|
-
$routerProvider.$inject = ["$locationProvider"];
|
|
21
|
-
/** This angular 1 provider instantiates a Router and exposes its services via the angular injector */
|
|
22
|
-
export function $routerProvider($locationProvider) {
|
|
23
|
-
// Create a new instance of the Router when the $routerProvider is initialized
|
|
24
|
-
router = this.router = new UIRouter($locationProvider);
|
|
25
|
-
router.stateProvider = new StateProvider(
|
|
26
|
-
router.stateRegistry,
|
|
27
|
-
router.stateService,
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Applys ng1-specific path parameter encoding
|
|
32
|
-
*
|
|
33
|
-
* The Angular 1 `$location` service is a bit weird.
|
|
34
|
-
* It doesn't allow slashes to be encoded/decoded bi-directionally.
|
|
35
|
-
*
|
|
36
|
-
* See the writeup at https://github.com/angular-ui/ui-router/issues/2598
|
|
37
|
-
*
|
|
38
|
-
* This code patches the `path` parameter type so it encoded/decodes slashes as ~2F
|
|
39
|
-
*
|
|
40
|
-
*/
|
|
41
|
-
const pathType = router.urlMatcherFactory.type("path");
|
|
42
|
-
pathType.encode = (x) =>
|
|
43
|
-
x != null
|
|
44
|
-
? x.toString().replace(/(~|\/)/g, (m) => ({ "~": "~~", "/": "~2F" })[m])
|
|
45
|
-
: x;
|
|
46
|
-
pathType.decode = (x) =>
|
|
47
|
-
x != null
|
|
48
|
-
? x.toString().replace(/(~~|~2F)/g, (m) => ({ "~~": "~", "~2F": "/" })[m])
|
|
49
|
-
: x;
|
|
50
|
-
|
|
51
|
-
// backwards compat: also expose router instance as $routerProvider.router
|
|
52
|
-
router["router"] = router;
|
|
53
|
-
router["$get"] = $get;
|
|
54
|
-
$get.$inject = ["$location", "$browser", "$rootScope", "$injector"];
|
|
55
|
-
function $get($location, $browser, $rootScope, $injector) {
|
|
56
|
-
router.stateRegistry.init($injector);
|
|
57
|
-
router.urlService._runtimeServices($rootScope, $location, $browser);
|
|
58
|
-
return router;
|
|
59
|
-
}
|
|
60
|
-
return router;
|
|
61
|
-
}
|
|
62
|
-
export const getProviderFor = (serviceName) => [
|
|
63
|
-
"$routerProvider",
|
|
64
|
-
function UrlServiceProvider($urp) {
|
|
65
|
-
const service = $urp.router[serviceName];
|
|
66
|
-
service["$get"] = () => service;
|
|
67
|
-
return service;
|
|
68
|
-
},
|
|
69
|
-
];
|
|
70
|
-
// This effectively calls $get() on `$routerProvider` to trigger init (when ng enters runtime)
|
|
71
|
-
runBlock.$inject = ["$injector", "$q", "$router"];
|
|
72
|
-
export function runBlock($injector, $q, $router) {
|
|
15
|
+
runBlock.$inject = ["$injector", "$q", "$stateRegistry", "$urlService"];
|
|
16
|
+
export function runBlock($injector, $q, $stateRegistry, $urlService) {
|
|
73
17
|
services.$injector = $injector;
|
|
74
18
|
services.$q = $q;
|
|
75
19
|
// https://github.com/angular-ui/ui-router/issues/3678
|
|
@@ -82,7 +26,7 @@ export function runBlock($injector, $q, $router) {
|
|
|
82
26
|
}
|
|
83
27
|
// The $injector is now available.
|
|
84
28
|
// Find any resolvables that had dependency annotation deferred
|
|
85
|
-
$
|
|
29
|
+
$stateRegistry
|
|
86
30
|
.get()
|
|
87
31
|
.map((x) => x.$$state().resolvables)
|
|
88
32
|
.reduce(unnestR, [])
|
|
@@ -94,16 +38,8 @@ export function runBlock($injector, $q, $router) {
|
|
|
94
38
|
$injector.strictDi,
|
|
95
39
|
)),
|
|
96
40
|
);
|
|
97
|
-
//
|
|
98
|
-
$
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// $state service and $stateProvider
|
|
102
|
-
// $urlRouter service and $urlRouterProvider
|
|
103
|
-
export function getStateProvider() {
|
|
104
|
-
return Object.assign(router.stateProvider, {
|
|
105
|
-
$get: () => router.stateService,
|
|
106
|
-
});
|
|
41
|
+
// Start listening for url changes
|
|
42
|
+
$urlService.listen();
|
|
107
43
|
}
|
|
108
44
|
|
|
109
45
|
watchDigests.$inject = ["$rootScope"];
|
|
@@ -112,17 +48,3 @@ export function watchDigests($rootScope) {
|
|
|
112
48
|
trace.approximateDigests++;
|
|
113
49
|
});
|
|
114
50
|
}
|
|
115
|
-
|
|
116
|
-
/** @hidden TODO: find a place to move this */
|
|
117
|
-
export const getLocals = (ctx) => {
|
|
118
|
-
const tokens = ctx.getTokens().filter(isString);
|
|
119
|
-
const tuples = tokens.map((key) => {
|
|
120
|
-
const resolvable = ctx.getResolvable(key);
|
|
121
|
-
const waitPolicy = ctx.getPolicy(resolvable).async;
|
|
122
|
-
return [
|
|
123
|
-
key,
|
|
124
|
-
waitPolicy === "NOWAIT" ? resolvable.promise : resolvable.data,
|
|
125
|
-
];
|
|
126
|
-
});
|
|
127
|
-
return tuples.reduce(applyPairs, {});
|
|
128
|
-
};
|
|
@@ -29,7 +29,7 @@ function dataBuilder(state) {
|
|
|
29
29
|
}
|
|
30
30
|
return state.data;
|
|
31
31
|
}
|
|
32
|
-
const getUrlBuilder = ($
|
|
32
|
+
const getUrlBuilder = ($urlService, root) =>
|
|
33
33
|
function urlBuilder(stateObject) {
|
|
34
34
|
let stateDec = stateObject.self;
|
|
35
35
|
// For future states, i.e., states whose name ends with `.**`,
|
|
@@ -49,9 +49,9 @@ const getUrlBuilder = ($urlMatcherFactoryProvider, root) =>
|
|
|
49
49
|
const parsed = parseUrl(stateDec.url);
|
|
50
50
|
const url = !parsed
|
|
51
51
|
? stateDec.url
|
|
52
|
-
: $
|
|
52
|
+
: $urlService.compile(parsed.val, { state: stateDec });
|
|
53
53
|
if (!url) return null;
|
|
54
|
-
if (!$
|
|
54
|
+
if (!$urlService.isMatcher(url))
|
|
55
55
|
throw new Error(`Invalid url '${url}' in state '${stateObject}'`);
|
|
56
56
|
return parsed && parsed.root
|
|
57
57
|
? url
|
|
@@ -238,7 +238,7 @@ export function resolvablesBuilder(state) {
|
|
|
238
238
|
* using the [[builder]] method.
|
|
239
239
|
*/
|
|
240
240
|
export class StateBuilder {
|
|
241
|
-
constructor(matcher,
|
|
241
|
+
constructor(matcher, urlService) {
|
|
242
242
|
this.matcher = matcher;
|
|
243
243
|
this.$injector = undefined;
|
|
244
244
|
const self = this;
|
|
@@ -254,10 +254,11 @@ export class StateBuilder {
|
|
|
254
254
|
parent: [parentBuilder],
|
|
255
255
|
data: [dataBuilder],
|
|
256
256
|
// Build a URLMatcher if necessary, either via a relative or absolute URL
|
|
257
|
-
url: [getUrlBuilder(
|
|
257
|
+
url: [getUrlBuilder(urlService, root)],
|
|
258
258
|
// Keep track of the closest ancestor state that has a URL (i.e. is navigable)
|
|
259
259
|
navigable: [getNavigableBuilder(isRoot)],
|
|
260
|
-
|
|
260
|
+
// TODO
|
|
261
|
+
params: [getParamsBuilder(urlService.paramFactory)],
|
|
261
262
|
// Each framework-specific ui-router implementation should define its own `views` builder
|
|
262
263
|
// e.g., src/ng1/statebuilders/views.ts
|
|
263
264
|
views: [],
|
|
@@ -32,7 +32,8 @@ export class StateQueueManager {
|
|
|
32
32
|
orphans = [], // states that don't yet have a parent registered
|
|
33
33
|
previousQueueLength = {}; // keep track of how long the queue when an orphan was first encountered
|
|
34
34
|
const getState = (name) =>
|
|
35
|
-
|
|
35
|
+
Object.prototype.hasOwnProperty.call(this.states, name) &&
|
|
36
|
+
this.states[name];
|
|
36
37
|
const notifyListeners = () => {
|
|
37
38
|
if (registered.length) {
|
|
38
39
|
this.listeners.forEach((listener) =>
|
|
@@ -1,24 +1,32 @@
|
|
|
1
1
|
import { StateMatcher } from "./state-matcher";
|
|
2
2
|
import { StateBuilder } from "./state-builder";
|
|
3
3
|
import { StateQueueManager } from "./state-queue-manager";
|
|
4
|
-
import { removeFrom } from "../../shared/common";
|
|
4
|
+
import { applyPairs, removeFrom } from "../../shared/common";
|
|
5
5
|
import { propEq } from "../../shared/hof";
|
|
6
6
|
import { ResolveContext } from "../resolve/resolve-context";
|
|
7
|
-
import { getLocals } from "../services";
|
|
8
7
|
import { ng1ViewsBuilder } from "./views";
|
|
8
|
+
import { isString } from "../../shared/utils";
|
|
9
9
|
/**
|
|
10
10
|
* A registry for all of the application's [[StateDeclaration]]s
|
|
11
11
|
*
|
|
12
12
|
* This API is found at `$stateRegistry` ([[UIRouter.stateRegistry]])
|
|
13
13
|
*/
|
|
14
14
|
export class StateRegistry {
|
|
15
|
-
|
|
15
|
+
static $inject = [
|
|
16
|
+
"$urlServiceProvider",
|
|
17
|
+
"$stateProvider",
|
|
18
|
+
"$routerGlobalsProvider",
|
|
19
|
+
"$viewProvider",
|
|
20
|
+
];
|
|
21
|
+
constructor(urlService, stateService, globals, viewService) {
|
|
16
22
|
this.states = {};
|
|
17
|
-
|
|
23
|
+
stateService.stateRegistry = this; // <- circular wiring
|
|
24
|
+
this.urlService = urlService;
|
|
25
|
+
this.urlServiceRules = urlService.rules;
|
|
18
26
|
this.$injector = undefined;
|
|
19
27
|
this.listeners = [];
|
|
20
28
|
this.matcher = new StateMatcher(this.states);
|
|
21
|
-
this.builder = new StateBuilder(this.matcher,
|
|
29
|
+
this.builder = new StateBuilder(this.matcher, urlService);
|
|
22
30
|
// Apply ng1 specific StateBuilder code for `views`, `resolve`, and `onExit/Retain/Enter` properties
|
|
23
31
|
// TODO we can probably move this inside buildr
|
|
24
32
|
this.builder.builder("views", ng1ViewsBuilder);
|
|
@@ -28,22 +36,27 @@ export class StateRegistry {
|
|
|
28
36
|
|
|
29
37
|
this.stateQueue = new StateQueueManager(
|
|
30
38
|
this,
|
|
31
|
-
urlServiceRules,
|
|
39
|
+
this.urlServiceRules,
|
|
32
40
|
this.states,
|
|
33
41
|
this.builder,
|
|
34
42
|
this.listeners,
|
|
35
43
|
);
|
|
36
44
|
this._registerRoot();
|
|
37
|
-
}
|
|
38
45
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
init($injector) {
|
|
43
|
-
this.$injector = $injector;
|
|
44
|
-
this.builder.$injector = $injector;
|
|
46
|
+
viewService._pluginapi._rootViewContext(this.root());
|
|
47
|
+
globals.$current = this.root();
|
|
48
|
+
globals.current = globals.$current.self;
|
|
45
49
|
}
|
|
46
50
|
|
|
51
|
+
$get = [
|
|
52
|
+
"$injector",
|
|
53
|
+
($injector) => {
|
|
54
|
+
this.$injector = $injector;
|
|
55
|
+
this.builder.$injector = $injector;
|
|
56
|
+
return this;
|
|
57
|
+
},
|
|
58
|
+
];
|
|
59
|
+
|
|
47
60
|
/**
|
|
48
61
|
* This is a [[StateBuilder.builder]] function for angular1 `onEnter`, `onExit`,
|
|
49
62
|
* `onRetain` callback hooks on a [[Ng1StateDeclaration]].
|
|
@@ -214,12 +227,17 @@ export class StateRegistry {
|
|
|
214
227
|
decorator(property, builderFunction) {
|
|
215
228
|
return this.builder.builder(property, builderFunction);
|
|
216
229
|
}
|
|
217
|
-
|
|
218
|
-
$get = [
|
|
219
|
-
"$injector",
|
|
220
|
-
function ($injector) {
|
|
221
|
-
this.init($injector);
|
|
222
|
-
return this;
|
|
223
|
-
},
|
|
224
|
-
];
|
|
225
230
|
}
|
|
231
|
+
|
|
232
|
+
export const getLocals = (ctx) => {
|
|
233
|
+
const tokens = ctx.getTokens().filter(isString);
|
|
234
|
+
const tuples = tokens.map((key) => {
|
|
235
|
+
const resolvable = ctx.getResolvable(key);
|
|
236
|
+
const waitPolicy = ctx.getPolicy(resolvable).async;
|
|
237
|
+
return [
|
|
238
|
+
key,
|
|
239
|
+
waitPolicy === "NOWAIT" ? resolvable.promise : resolvable.data,
|
|
240
|
+
];
|
|
241
|
+
});
|
|
242
|
+
return tuples.reduce(applyPairs, {});
|
|
243
|
+
};
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
silenceUncaughtInPromise,
|
|
7
7
|
silentRejection,
|
|
8
8
|
} from "../../shared/common";
|
|
9
|
-
import { isDefined, isObject, isString } from "../../shared/utils";
|
|
9
|
+
import { isDefined, isObject, isString, minErr } from "../../shared/utils";
|
|
10
10
|
import { Queue } from "../common/queue";
|
|
11
11
|
import { services } from "../common/coreservices";
|
|
12
12
|
import { PathUtils } from "../path/path-utils";
|
|
@@ -21,6 +21,42 @@ import { lazyLoadState } from "../hooks/lazy-load";
|
|
|
21
21
|
import { not, val } from "../../shared/hof";
|
|
22
22
|
import { EventBus } from "../../core/pubsub";
|
|
23
23
|
|
|
24
|
+
const err = minErr("$stateProvider");
|
|
25
|
+
// Right now this is a collection of all the properties we encounter in tests
|
|
26
|
+
const validKeys = [
|
|
27
|
+
"$$state",
|
|
28
|
+
"__stateObjectCache",
|
|
29
|
+
"abstract",
|
|
30
|
+
"bindings",
|
|
31
|
+
"controller",
|
|
32
|
+
"controllerAs",
|
|
33
|
+
"controllerProvider",
|
|
34
|
+
"component",
|
|
35
|
+
"componentProvider",
|
|
36
|
+
"data",
|
|
37
|
+
"includes",
|
|
38
|
+
"lazyLoad",
|
|
39
|
+
"name",
|
|
40
|
+
"navigable",
|
|
41
|
+
"onEnter",
|
|
42
|
+
"onExit",
|
|
43
|
+
"onRetain",
|
|
44
|
+
"params",
|
|
45
|
+
"parent",
|
|
46
|
+
"path",
|
|
47
|
+
"redirectTo",
|
|
48
|
+
"reloadOnSearch",
|
|
49
|
+
"resolve",
|
|
50
|
+
"resolveAs",
|
|
51
|
+
"resolvables",
|
|
52
|
+
"self",
|
|
53
|
+
"template",
|
|
54
|
+
"templateProvider",
|
|
55
|
+
"templateUrl",
|
|
56
|
+
"url",
|
|
57
|
+
"views",
|
|
58
|
+
];
|
|
59
|
+
|
|
24
60
|
/**
|
|
25
61
|
* Provides services related to ui-router states.
|
|
26
62
|
*
|
|
@@ -52,10 +88,11 @@ export class StateService {
|
|
|
52
88
|
return this.globals.$current;
|
|
53
89
|
}
|
|
54
90
|
|
|
55
|
-
|
|
91
|
+
static $inject = ["$routerGlobalsProvider", "$transitionsProvider"];
|
|
92
|
+
|
|
93
|
+
// Needs access to urlService, stateRegistry
|
|
56
94
|
constructor(globals, transitionService) {
|
|
57
95
|
this.stateRegistry = undefined;
|
|
58
|
-
this.urlRouter = undefined;
|
|
59
96
|
this.urlService = undefined;
|
|
60
97
|
this.globals = globals;
|
|
61
98
|
this.transitionService = transitionService;
|
|
@@ -86,6 +123,136 @@ export class StateService {
|
|
|
86
123
|
);
|
|
87
124
|
}
|
|
88
125
|
|
|
126
|
+
$get = [
|
|
127
|
+
() => {
|
|
128
|
+
return this;
|
|
129
|
+
},
|
|
130
|
+
];
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Decorates states when they are registered
|
|
134
|
+
*
|
|
135
|
+
* Allows you to extend (carefully) or override (at your own peril) the
|
|
136
|
+
* `stateBuilder` object used internally by [[StateRegistry]].
|
|
137
|
+
* This can be used to add custom functionality to ui-router,
|
|
138
|
+
* for example inferring templateUrl based on the state name.
|
|
139
|
+
*
|
|
140
|
+
* When passing only a name, it returns the current (original or decorated) builder
|
|
141
|
+
* function that matches `name`.
|
|
142
|
+
*
|
|
143
|
+
* The builder functions that can be decorated are listed below. Though not all
|
|
144
|
+
* necessarily have a good use case for decoration, that is up to you to decide.
|
|
145
|
+
*
|
|
146
|
+
* In addition, users can attach custom decorators, which will generate new
|
|
147
|
+
* properties within the state's internal definition. There is currently no clear
|
|
148
|
+
* use-case for this beyond accessing internal states (i.e. $state.$current),
|
|
149
|
+
* however, expect this to become increasingly relevant as we introduce additional
|
|
150
|
+
* meta-programming features.
|
|
151
|
+
*
|
|
152
|
+
* **Warning**: Decorators should not be interdependent because the order of
|
|
153
|
+
* execution of the builder functions in non-deterministic. Builder functions
|
|
154
|
+
* should only be dependent on the state definition object and super function.
|
|
155
|
+
*
|
|
156
|
+
*
|
|
157
|
+
* Existing builder functions and current return values:
|
|
158
|
+
*
|
|
159
|
+
* - **parent** `{object}` - returns the parent state object.
|
|
160
|
+
* - **data** `{object}` - returns state data, including any inherited data that is not
|
|
161
|
+
* overridden by own values (if any).
|
|
162
|
+
* - **url** `{object}` - returns a {@link ui.router.util.type:UrlMatcher UrlMatcher}
|
|
163
|
+
* or `null`.
|
|
164
|
+
* - **navigable** `{object}` - returns closest ancestor state that has a URL (aka is
|
|
165
|
+
* navigable).
|
|
166
|
+
* - **params** `{object}` - returns an array of state params that are ensured to
|
|
167
|
+
* be a super-set of parent's params.
|
|
168
|
+
* - **views** `{object}` - returns a views object where each key is an absolute view
|
|
169
|
+
* name (i.e. "viewName@stateName") and each value is the config object
|
|
170
|
+
* (template, controller) for the view. Even when you don't use the views object
|
|
171
|
+
* explicitly on a state config, one is still created for you internally.
|
|
172
|
+
* So by decorating this builder function you have access to decorating template
|
|
173
|
+
* and controller properties.
|
|
174
|
+
* - **ownParams** `{object}` - returns an array of params that belong to the state,
|
|
175
|
+
* not including any params defined by ancestor states.
|
|
176
|
+
* - **path** `{string}` - returns the full path from the root down to this state.
|
|
177
|
+
* Needed for state activation.
|
|
178
|
+
* - **includes** `{object}` - returns an object that includes every state that
|
|
179
|
+
* would pass a `$state.includes()` test.
|
|
180
|
+
*
|
|
181
|
+
* #### Example:
|
|
182
|
+
* Override the internal 'views' builder with a function that takes the state
|
|
183
|
+
* definition, and a reference to the internal function being overridden:
|
|
184
|
+
* ```js
|
|
185
|
+
* $stateProvider.decorator('views', function (state, parent) {
|
|
186
|
+
* let result = {},
|
|
187
|
+
* views = parent(state);
|
|
188
|
+
*
|
|
189
|
+
* angular.forEach(views, function (config, name) {
|
|
190
|
+
* let autoName = (state.name + '.' + name).replace('.', '/');
|
|
191
|
+
* config.templateUrl = config.templateUrl || '/partials/' + autoName + '.html';
|
|
192
|
+
* result[name] = config;
|
|
193
|
+
* });
|
|
194
|
+
* return result;
|
|
195
|
+
* });
|
|
196
|
+
*
|
|
197
|
+
* $stateProvider.state('home', {
|
|
198
|
+
* views: {
|
|
199
|
+
* 'contact.list': { controller: 'ListController' },
|
|
200
|
+
* 'contact.item': { controller: 'ItemController' }
|
|
201
|
+
* }
|
|
202
|
+
* });
|
|
203
|
+
* ```
|
|
204
|
+
*
|
|
205
|
+
*
|
|
206
|
+
* ```js
|
|
207
|
+
* // Auto-populates list and item views with /partials/home/contact/list.html,
|
|
208
|
+
* // and /partials/home/contact/item.html, respectively.
|
|
209
|
+
* $state.go('home');
|
|
210
|
+
* ```
|
|
211
|
+
*
|
|
212
|
+
* @param {string} name The name of the builder function to decorate.
|
|
213
|
+
* @param {object} func A function that is responsible for decorating the original
|
|
214
|
+
* builder function. The function receives two parameters:
|
|
215
|
+
*
|
|
216
|
+
* - `{object}` - state - The state config object.
|
|
217
|
+
* - `{object}` - super - The original builder function.
|
|
218
|
+
*
|
|
219
|
+
* @return {object} $stateProvider - $stateProvider instance
|
|
220
|
+
*/
|
|
221
|
+
decorator(name, func) {
|
|
222
|
+
return this.stateRegistry.decorator(name, func) || this;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
*
|
|
227
|
+
* @param {angular.Ng1StateDeclaration} definition
|
|
228
|
+
*/
|
|
229
|
+
state(definition) {
|
|
230
|
+
if (!definition.name) {
|
|
231
|
+
throw err("stateinvalid", `'name' required`);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const hasInvalidKeys = Object.keys(definition).filter(
|
|
235
|
+
(key) => !validKeys.includes(key),
|
|
236
|
+
);
|
|
237
|
+
if (hasInvalidKeys.length) {
|
|
238
|
+
throw err("stateinvalid", `Invalid key(s): ${hasInvalidKeys.join(", ")}`);
|
|
239
|
+
}
|
|
240
|
+
try {
|
|
241
|
+
this.stateRegistry.register(definition);
|
|
242
|
+
} catch (e) {
|
|
243
|
+
throw err("stateinvalid", e.message);
|
|
244
|
+
}
|
|
245
|
+
return this;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Registers an invalid state handler
|
|
249
|
+
*
|
|
250
|
+
* This is a passthrough to [[StateService.onInvalid]] for ng1.
|
|
251
|
+
*/
|
|
252
|
+
onInvalid(callback) {
|
|
253
|
+
return this.onInvalid(callback);
|
|
254
|
+
}
|
|
255
|
+
|
|
89
256
|
/**
|
|
90
257
|
* Handler for when [[transitionTo]] is called with an invalid state.
|
|
91
258
|
*
|
|
@@ -344,7 +511,7 @@ export class StateService {
|
|
|
344
511
|
if (error instanceof Rejection) {
|
|
345
512
|
const isLatest = this.globals.lastStartedTransitionId <= trans.$id;
|
|
346
513
|
if (error.type === RejectType.IGNORED) {
|
|
347
|
-
isLatest &&
|
|
514
|
+
isLatest && this.urlService.update();
|
|
348
515
|
// Consider ignored `Transition.run()` as a successful `transitionTo`
|
|
349
516
|
return services.$q.when(this.globals.current);
|
|
350
517
|
}
|
|
@@ -360,7 +527,7 @@ export class StateService {
|
|
|
360
527
|
return redirect.run().catch(rejectedTransitionHandler(redirect));
|
|
361
528
|
}
|
|
362
529
|
if (error.type === RejectType.ABORTED) {
|
|
363
|
-
isLatest &&
|
|
530
|
+
isLatest && this.urlService.update();
|
|
364
531
|
return services.$q.reject(error);
|
|
365
532
|
}
|
|
366
533
|
}
|
|
@@ -519,7 +686,7 @@ export class StateService {
|
|
|
519
686
|
if (!nav || nav.url === undefined || nav.url === null) {
|
|
520
687
|
return null;
|
|
521
688
|
}
|
|
522
|
-
return this.
|
|
689
|
+
return this.urlService.href(nav.url, params, {
|
|
523
690
|
absolute: options.absolute,
|
|
524
691
|
});
|
|
525
692
|
}
|
|
@@ -3,7 +3,6 @@ import { isDefined, isString } from "../../shared/utils";
|
|
|
3
3
|
import { isInjectable } from "../../shared/predicates";
|
|
4
4
|
import { services } from "../common/coreservices";
|
|
5
5
|
import { trace } from "../common/trace";
|
|
6
|
-
import { ViewService } from "../view/view";
|
|
7
6
|
import { ResolveContext } from "../resolve/resolve-context";
|
|
8
7
|
import { Resolvable } from "../resolve/resolvable";
|
|
9
8
|
|
|
@@ -77,7 +76,7 @@ export function ng1ViewsBuilder(state) {
|
|
|
77
76
|
config.$type = "ng1";
|
|
78
77
|
config.$context = state;
|
|
79
78
|
config.$name = name;
|
|
80
|
-
const normalized =
|
|
79
|
+
const normalized = Ng1ViewConfig.normalizeUIViewTarget(
|
|
81
80
|
config.$context,
|
|
82
81
|
config.$name,
|
|
83
82
|
);
|
|
@@ -144,4 +143,49 @@ export class Ng1ViewConfig {
|
|
|
144
143
|
const resolvable = new Resolvable("", providerFn, deps);
|
|
145
144
|
return resolvable.get(context);
|
|
146
145
|
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Normalizes a view's name from a state.views configuration block.
|
|
149
|
+
*
|
|
150
|
+
* This should be used by a framework implementation to calculate the values for
|
|
151
|
+
* [[_ViewDeclaration.$ngViewName]] and [[_ViewDeclaration.$ngViewContextAnchor]].
|
|
152
|
+
*
|
|
153
|
+
* @param context the context object (state declaration) that the view belongs to
|
|
154
|
+
* @param rawViewName the name of the view, as declared in the [[StateDeclaration.views]]
|
|
155
|
+
*
|
|
156
|
+
* @returns the normalized ngViewName and ngViewContextAnchor that the view targets
|
|
157
|
+
*/
|
|
158
|
+
static normalizeUIViewTarget(context, rawViewName = "") {
|
|
159
|
+
// TODO: Validate incoming view name with a regexp to allow:
|
|
160
|
+
// ex: "view.name@foo.bar" , "^.^.view.name" , "view.name@^.^" , "" ,
|
|
161
|
+
// "@" , "$default@^" , "!$default.$default" , "!foo.bar"
|
|
162
|
+
const viewAtContext = rawViewName.split("@");
|
|
163
|
+
let ngViewName = viewAtContext[0] || "$default"; // default to unnamed view
|
|
164
|
+
let ngViewContextAnchor = isString(viewAtContext[1])
|
|
165
|
+
? viewAtContext[1]
|
|
166
|
+
: "^"; // default to parent context
|
|
167
|
+
// Handle relative view-name sugar syntax.
|
|
168
|
+
// Matches rawViewName "^.^.^.foo.bar" into array: ["^.^.^.foo.bar", "^.^.^", "foo.bar"],
|
|
169
|
+
const relativeViewNameSugar = /^(\^(?:\.\^)*)\.(.*$)/.exec(ngViewName);
|
|
170
|
+
if (relativeViewNameSugar) {
|
|
171
|
+
// Clobbers existing contextAnchor (rawViewName validation will fix this)
|
|
172
|
+
ngViewContextAnchor = relativeViewNameSugar[1]; // set anchor to "^.^.^"
|
|
173
|
+
ngViewName = relativeViewNameSugar[2]; // set view-name to "foo.bar"
|
|
174
|
+
}
|
|
175
|
+
if (ngViewName.charAt(0) === "!") {
|
|
176
|
+
ngViewName = ngViewName.substr(1);
|
|
177
|
+
ngViewContextAnchor = ""; // target absolutely from root
|
|
178
|
+
}
|
|
179
|
+
// handle parent relative targeting "^.^.^"
|
|
180
|
+
const relativeMatch = /^(\^(?:\.\^)*)$/;
|
|
181
|
+
if (relativeMatch.exec(ngViewContextAnchor)) {
|
|
182
|
+
const anchorState = ngViewContextAnchor
|
|
183
|
+
.split(".")
|
|
184
|
+
.reduce((anchor) => anchor.parent, context);
|
|
185
|
+
ngViewContextAnchor = anchorState.name;
|
|
186
|
+
} else if (ngViewContextAnchor === ".") {
|
|
187
|
+
ngViewContextAnchor = context.name;
|
|
188
|
+
}
|
|
189
|
+
return { ngViewName, ngViewContextAnchor };
|
|
190
|
+
}
|
|
147
191
|
}
|
|
@@ -54,14 +54,6 @@ export const RejectType = {
|
|
|
54
54
|
|
|
55
55
|
let id = 0;
|
|
56
56
|
export class Rejection {
|
|
57
|
-
/** Returns true if the obj is a rejected promise created from the `asPromise` factory */
|
|
58
|
-
static isRejectionPromise(obj) {
|
|
59
|
-
return (
|
|
60
|
-
obj &&
|
|
61
|
-
typeof obj.then === "function" &&
|
|
62
|
-
is(Rejection)(obj._transitionRejection)
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
57
|
/** Returns a Rejection due to transition superseded */
|
|
66
58
|
static superseded(detail, options) {
|
|
67
59
|
const message =
|