@angular-wave/angular.ts 0.0.31 → 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/index.js +23 -21
- package/src/router/services.js +6 -62
- package/src/router/state/state-queue-manager.js +2 -1
- package/src/router/state/state-registry.js +35 -18
- package/src/router/state/state-service.js +169 -1
- 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 +7 -1
- package/src/router/url/url-rule.js +4 -4
- package/src/router/url/url-service.js +32 -15
- package/src/router/view/view.js +7 -51
- package/src/services/http.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 +7 -15
- 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-service.spec.js +4 -6
- package/test/router/view-directive.spec.js +9 -9
- package/test/router/view-hook.spec.js +10 -10
- 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 -103
- package/test/original-test.html +0 -33
package/src/router/services.js
CHANGED
|
@@ -9,46 +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
|
-
// backwards compat: also expose router instance as $routerProvider.router
|
|
31
|
-
router["router"] = router;
|
|
32
|
-
router["$get"] = $get;
|
|
33
|
-
$get.$inject = ["$location", "$browser", "$rootScope", "$injector"];
|
|
34
|
-
function $get($location, $browser, $rootScope, $injector) {
|
|
35
|
-
router.stateRegistry.init($injector);
|
|
36
|
-
router.urlService._runtimeServices($rootScope, $location, $browser);
|
|
37
|
-
return router;
|
|
38
|
-
}
|
|
39
|
-
return router;
|
|
40
|
-
}
|
|
41
|
-
export const getProviderFor = (serviceName) => [
|
|
42
|
-
"$routerProvider",
|
|
43
|
-
function UrlServiceProvider($urp) {
|
|
44
|
-
const service = $urp.router[serviceName];
|
|
45
|
-
service["$get"] = () => service;
|
|
46
|
-
return service;
|
|
47
|
-
},
|
|
48
|
-
];
|
|
49
|
-
// This effectively calls $get() on `$routerProvider` to trigger init (when ng enters runtime)
|
|
50
|
-
runBlock.$inject = ["$injector", "$q", "$router"];
|
|
51
|
-
export function runBlock($injector, $q, $router) {
|
|
15
|
+
runBlock.$inject = ["$injector", "$q", "$stateRegistry", "$urlService"];
|
|
16
|
+
export function runBlock($injector, $q, $stateRegistry, $urlService) {
|
|
52
17
|
services.$injector = $injector;
|
|
53
18
|
services.$q = $q;
|
|
54
19
|
// https://github.com/angular-ui/ui-router/issues/3678
|
|
@@ -61,7 +26,7 @@ export function runBlock($injector, $q, $router) {
|
|
|
61
26
|
}
|
|
62
27
|
// The $injector is now available.
|
|
63
28
|
// Find any resolvables that had dependency annotation deferred
|
|
64
|
-
$
|
|
29
|
+
$stateRegistry
|
|
65
30
|
.get()
|
|
66
31
|
.map((x) => x.$$state().resolvables)
|
|
67
32
|
.reduce(unnestR, [])
|
|
@@ -73,15 +38,8 @@ export function runBlock($injector, $q, $router) {
|
|
|
73
38
|
$injector.strictDi,
|
|
74
39
|
)),
|
|
75
40
|
);
|
|
76
|
-
//
|
|
77
|
-
$
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// $state service and $stateProvider
|
|
81
|
-
export function getStateProvider() {
|
|
82
|
-
return Object.assign(router.stateProvider, {
|
|
83
|
-
$get: () => router.stateService,
|
|
84
|
-
});
|
|
41
|
+
// Start listening for url changes
|
|
42
|
+
$urlService.listen();
|
|
85
43
|
}
|
|
86
44
|
|
|
87
45
|
watchDigests.$inject = ["$rootScope"];
|
|
@@ -90,17 +48,3 @@ export function watchDigests($rootScope) {
|
|
|
90
48
|
trace.approximateDigests++;
|
|
91
49
|
});
|
|
92
50
|
}
|
|
93
|
-
|
|
94
|
-
/** @hidden TODO: find a place to move this */
|
|
95
|
-
export const getLocals = (ctx) => {
|
|
96
|
-
const tokens = ctx.getTokens().filter(isString);
|
|
97
|
-
const tuples = tokens.map((key) => {
|
|
98
|
-
const resolvable = ctx.getResolvable(key);
|
|
99
|
-
const waitPolicy = ctx.getPolicy(resolvable).async;
|
|
100
|
-
return [
|
|
101
|
-
key,
|
|
102
|
-
waitPolicy === "NOWAIT" ? resolvable.promise : resolvable.data,
|
|
103
|
-
];
|
|
104
|
-
});
|
|
105
|
-
return tuples.reduce(applyPairs, {});
|
|
106
|
-
};
|
|
@@ -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,19 +1,26 @@
|
|
|
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 = {};
|
|
23
|
+
stateService.stateRegistry = this; // <- circular wiring
|
|
17
24
|
this.urlService = urlService;
|
|
18
25
|
this.urlServiceRules = urlService.rules;
|
|
19
26
|
this.$injector = undefined;
|
|
@@ -35,16 +42,21 @@ export class StateRegistry {
|
|
|
35
42
|
this.listeners,
|
|
36
43
|
);
|
|
37
44
|
this._registerRoot();
|
|
38
|
-
}
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
init($injector) {
|
|
44
|
-
this.$injector = $injector;
|
|
45
|
-
this.builder.$injector = $injector;
|
|
46
|
+
viewService._pluginapi._rootViewContext(this.root());
|
|
47
|
+
globals.$current = this.root();
|
|
48
|
+
globals.current = globals.$current.self;
|
|
46
49
|
}
|
|
47
50
|
|
|
51
|
+
$get = [
|
|
52
|
+
"$injector",
|
|
53
|
+
($injector) => {
|
|
54
|
+
this.$injector = $injector;
|
|
55
|
+
this.builder.$injector = $injector;
|
|
56
|
+
return this;
|
|
57
|
+
},
|
|
58
|
+
];
|
|
59
|
+
|
|
48
60
|
/**
|
|
49
61
|
* This is a [[StateBuilder.builder]] function for angular1 `onEnter`, `onExit`,
|
|
50
62
|
* `onRetain` callback hooks on a [[Ng1StateDeclaration]].
|
|
@@ -215,12 +227,17 @@ export class StateRegistry {
|
|
|
215
227
|
decorator(property, builderFunction) {
|
|
216
228
|
return this.builder.builder(property, builderFunction);
|
|
217
229
|
}
|
|
218
|
-
|
|
219
|
-
$get = [
|
|
220
|
-
"$injector",
|
|
221
|
-
function ($injector) {
|
|
222
|
-
this.init($injector);
|
|
223
|
-
return this;
|
|
224
|
-
},
|
|
225
|
-
];
|
|
226
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,6 +88,8 @@ export class StateService {
|
|
|
52
88
|
return this.globals.$current;
|
|
53
89
|
}
|
|
54
90
|
|
|
91
|
+
static $inject = ["$routerGlobalsProvider", "$transitionsProvider"];
|
|
92
|
+
|
|
55
93
|
// Needs access to urlService, stateRegistry
|
|
56
94
|
constructor(globals, transitionService) {
|
|
57
95
|
this.stateRegistry = undefined;
|
|
@@ -85,6 +123,136 @@ export class StateService {
|
|
|
85
123
|
);
|
|
86
124
|
}
|
|
87
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
|
+
|
|
88
256
|
/**
|
|
89
257
|
* Handler for when [[transitionTo]] is called with an invalid state.
|
|
90
258
|
*
|
|
@@ -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 =
|
|
@@ -15,7 +15,10 @@ import {
|
|
|
15
15
|
registerLazyResolveState,
|
|
16
16
|
registerResolveRemaining,
|
|
17
17
|
} from "../hooks/resolve";
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
registerActivateViews,
|
|
20
|
+
registerLoadEnteringViews,
|
|
21
|
+
} from "../hooks/views";
|
|
19
22
|
import { registerUpdateGlobalState } from "../hooks/update-globals";
|
|
20
23
|
|
|
21
24
|
import { registerLazyLoadHook } from "../hooks/lazy-load";
|
|
@@ -26,6 +29,8 @@ import { createProxyFunctions } from "../../shared/common";
|
|
|
26
29
|
import { val } from "../../shared/hof";
|
|
27
30
|
import { registerIgnoredTransitionHook } from "../hooks/ignored-transition";
|
|
28
31
|
import { registerInvalidTransitionHook } from "../hooks/invalid-transition";
|
|
32
|
+
import { registerRedirectToHook } from "../hooks/redirect-to";
|
|
33
|
+
import { registerUpdateUrl } from "../hooks/url";
|
|
29
34
|
/**
|
|
30
35
|
* The default [[Transition]] options.
|
|
31
36
|
*
|
|
@@ -56,6 +61,8 @@ export let defaultTransOpts = {
|
|
|
56
61
|
* This API is located at `router.transitionService` ([[UIRouter.transitionService]])
|
|
57
62
|
*/
|
|
58
63
|
export class TransitionService {
|
|
64
|
+
static $inject = ["$routerGlobalsProvider", "$viewProvider"];
|
|
65
|
+
|
|
59
66
|
/**
|
|
60
67
|
* @param {import('../globals').UIRouterGlobals} globals
|
|
61
68
|
*/
|
|
@@ -82,6 +89,41 @@ export class TransitionService {
|
|
|
82
89
|
this._registerCoreTransitionHooks();
|
|
83
90
|
globals.successfulTransitions.onEvict(treeChangesCleanup);
|
|
84
91
|
}
|
|
92
|
+
|
|
93
|
+
$get = [
|
|
94
|
+
"$state",
|
|
95
|
+
"$urlService",
|
|
96
|
+
"$stateRegistry",
|
|
97
|
+
"$view",
|
|
98
|
+
(stateService, urlService, stateRegistry, viewService) => {
|
|
99
|
+
// Lazy load state trees
|
|
100
|
+
this._deregisterHookFns.lazyLoad = registerLazyLoadHook(
|
|
101
|
+
this,
|
|
102
|
+
stateService,
|
|
103
|
+
urlService,
|
|
104
|
+
stateRegistry,
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// After globals.current is updated at priority: 10000
|
|
108
|
+
this._deregisterHookFns.updateUrl = registerUpdateUrl(
|
|
109
|
+
this,
|
|
110
|
+
stateService,
|
|
111
|
+
urlService,
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
// Wire up redirectTo hook
|
|
115
|
+
this._deregisterHookFns.redirectTo = registerRedirectToHook(
|
|
116
|
+
this,
|
|
117
|
+
stateService,
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
this._deregisterHookFns.activateViews = registerActivateViews(
|
|
121
|
+
this,
|
|
122
|
+
viewService,
|
|
123
|
+
);
|
|
124
|
+
return this;
|
|
125
|
+
},
|
|
126
|
+
];
|
|
85
127
|
/**
|
|
86
128
|
* Registers a [[TransitionHookFn]], called *while a transition is being constructed*.
|
|
87
129
|
*
|
|
@@ -13,7 +13,7 @@ import { isDefined, isString } from "../../shared/utils";
|
|
|
13
13
|
*
|
|
14
14
|
* This API is found at `router.urlService.config` (see: [[UIRouter.urlService]], [[URLService.config]])
|
|
15
15
|
*/
|
|
16
|
-
export class
|
|
16
|
+
export class UrlConfigProvider {
|
|
17
17
|
constructor() {
|
|
18
18
|
/** @type {ParamTypes} */
|
|
19
19
|
this.paramTypes = new ParamTypes();
|
|
@@ -49,6 +49,12 @@ export class UrlConfig {
|
|
|
49
49
|
this.paramTypes._flushTypeQueue();
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
$get = [
|
|
53
|
+
function () {
|
|
54
|
+
return this;
|
|
55
|
+
},
|
|
56
|
+
];
|
|
57
|
+
|
|
52
58
|
/**
|
|
53
59
|
* Defines whether URL matching should be case sensitive (the default behavior), or not.
|
|
54
60
|
*
|
|
@@ -13,8 +13,8 @@ import { StateObject } from "../state/state-object";
|
|
|
13
13
|
* - [[StateObject]]
|
|
14
14
|
*/
|
|
15
15
|
export class UrlRuleFactory {
|
|
16
|
-
constructor(
|
|
17
|
-
this.
|
|
16
|
+
constructor(urlService, stateService, routerGlobals) {
|
|
17
|
+
this.urlService = urlService;
|
|
18
18
|
this.stateService = stateService;
|
|
19
19
|
this.routerGlobals = routerGlobals;
|
|
20
20
|
}
|
|
@@ -28,7 +28,7 @@ export class UrlRuleFactory {
|
|
|
28
28
|
create(what, handler) {
|
|
29
29
|
const { isState, isStateDeclaration } = StateObject;
|
|
30
30
|
const makeRule = pattern([
|
|
31
|
-
[isString, (_what) => makeRule(this.
|
|
31
|
+
[isString, (_what) => makeRule(this.urlService.compile(_what))],
|
|
32
32
|
[is(UrlMatcher), (_what) => this.fromUrlMatcher(_what, handler)],
|
|
33
33
|
[
|
|
34
34
|
or(isState, isStateDeclaration),
|
|
@@ -79,7 +79,7 @@ export class UrlRuleFactory {
|
|
|
79
79
|
*/
|
|
80
80
|
fromUrlMatcher(urlMatcher, handler) {
|
|
81
81
|
let _handler = handler;
|
|
82
|
-
if (isString(handler)) handler = this.
|
|
82
|
+
if (isString(handler)) handler = this.urlService.compile(handler);
|
|
83
83
|
if (is(UrlMatcher)(handler)) _handler = (match) => handler.format(match);
|
|
84
84
|
function matchUrlParamters(url) {
|
|
85
85
|
const params = urlMatcher.exec(url.path, url.search, url.hash);
|
|
@@ -7,42 +7,55 @@ import {
|
|
|
7
7
|
} from "../../shared/utils";
|
|
8
8
|
import { is, pattern } from "../../shared/hof";
|
|
9
9
|
import { UrlRules } from "./url-rules";
|
|
10
|
-
import { UrlConfig } from "./url-config";
|
|
11
10
|
import { TargetState } from "../state/target-state";
|
|
12
11
|
import { removeFrom } from "../../shared/common";
|
|
13
12
|
import { stripLastPathElement } from "../../shared/strings";
|
|
14
13
|
import { UrlMatcher } from "./url-matcher";
|
|
15
14
|
import { ParamFactory } from "../params/param-factory";
|
|
15
|
+
import { UrlRuleFactory } from "./url-rule";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* API for URL management
|
|
19
19
|
*/
|
|
20
20
|
export class UrlService {
|
|
21
|
+
static $inject = [
|
|
22
|
+
"$locationProvider",
|
|
23
|
+
"$stateProvider",
|
|
24
|
+
"$routerGlobalsProvider",
|
|
25
|
+
"$urlConfigProvider",
|
|
26
|
+
];
|
|
27
|
+
|
|
21
28
|
/**
|
|
22
29
|
* @param {angular.ILocationProvider} $locationProvider
|
|
23
30
|
*/
|
|
24
|
-
constructor($locationProvider,
|
|
31
|
+
constructor($locationProvider, stateService, globals, urlConfigProvider) {
|
|
25
32
|
this.stateService = stateService;
|
|
33
|
+
this.stateService.urlService = this; // circular wiring
|
|
26
34
|
this.$locationProvider = $locationProvider;
|
|
35
|
+
|
|
27
36
|
this.$location = undefined;
|
|
28
37
|
this.$browser = undefined;
|
|
29
38
|
|
|
30
39
|
/** @type {boolean} */
|
|
31
40
|
this.interceptDeferred = false;
|
|
41
|
+
|
|
42
|
+
/** Provides services related to the URL */
|
|
43
|
+
this.urlRuleFactory = new UrlRuleFactory(this, this.stateService, globals);
|
|
44
|
+
|
|
32
45
|
/**
|
|
33
46
|
* The nested [[UrlRules]] API for managing URL rules and rewrites
|
|
34
47
|
*
|
|
35
48
|
* See: [[UrlRules]] for details
|
|
36
49
|
* @type {UrlRules}
|
|
37
50
|
*/
|
|
38
|
-
this.rules = new UrlRules(urlRuleFactory);
|
|
51
|
+
this.rules = new UrlRules(this.urlRuleFactory);
|
|
39
52
|
/**
|
|
40
53
|
* The nested [[UrlConfig]] API to configure the URL and retrieve URL information
|
|
41
54
|
*
|
|
42
55
|
* See: [[UrlConfig]] for details
|
|
43
|
-
* @type {UrlConfig}
|
|
56
|
+
* @type {angular.UrlConfig}
|
|
44
57
|
*/
|
|
45
|
-
this.config =
|
|
58
|
+
this.config = urlConfigProvider;
|
|
46
59
|
|
|
47
60
|
/** Creates a new [[Param]] for a given location (DefType) */
|
|
48
61
|
this.paramFactory = new ParamFactory(this.config);
|
|
@@ -75,6 +88,20 @@ export class UrlService {
|
|
|
75
88
|
this._urlListeners = [];
|
|
76
89
|
}
|
|
77
90
|
|
|
91
|
+
$get = [
|
|
92
|
+
"$location",
|
|
93
|
+
"$browser",
|
|
94
|
+
"$rootScope",
|
|
95
|
+
($location, $browser, $rootScope) => {
|
|
96
|
+
this.$location = $location;
|
|
97
|
+
this.$browser = $browser;
|
|
98
|
+
$rootScope.$on("$locationChangeSuccess", (evt) =>
|
|
99
|
+
this._urlListeners.forEach((fn) => fn(evt)),
|
|
100
|
+
);
|
|
101
|
+
return this;
|
|
102
|
+
},
|
|
103
|
+
];
|
|
104
|
+
|
|
78
105
|
html5Mode() {
|
|
79
106
|
let html5Mode = this.$locationProvider.html5Mode();
|
|
80
107
|
html5Mode = isObject(html5Mode) ? html5Mode.enabled : html5Mode;
|
|
@@ -316,16 +343,6 @@ export class UrlService {
|
|
|
316
343
|
return best;
|
|
317
344
|
}
|
|
318
345
|
|
|
319
|
-
_runtimeServices($rootScope, $location, $browser) {
|
|
320
|
-
/** @type {angular.ILocationService} */
|
|
321
|
-
this.$location = $location;
|
|
322
|
-
this.$browser = $browser;
|
|
323
|
-
// Bind $locationChangeSuccess to the listeners registered in LocationService.onChange
|
|
324
|
-
$rootScope.$on("$locationChangeSuccess", (evt) =>
|
|
325
|
-
this._urlListeners.forEach((fn) => fn(evt)),
|
|
326
|
-
);
|
|
327
|
-
}
|
|
328
|
-
|
|
329
346
|
update(read) {
|
|
330
347
|
if (read) {
|
|
331
348
|
this.location = this.url();
|