ember-source 4.3.0-alpha.3 → 4.4.0-alpha.2
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/CHANGELOG.md +6 -2
- package/blueprints/acceptance-test/mocha-files/tests/acceptance/__name__-test.js +4 -4
- package/blueprints/acceptance-test/mocha-rfc-232-files/tests/acceptance/__name__-test.js +2 -2
- package/blueprints/acceptance-test/qunit-files/tests/acceptance/__name__-test.js +2 -2
- package/blueprints/acceptance-test/qunit-rfc-232-files/tests/acceptance/__name__-test.js +2 -2
- package/blueprints/component/index.js +2 -2
- package/blueprints/component-class/index.js +2 -2
- package/blueprints/component-test/mocha-0.12-files/__root__/__testType__/__path__/__test__.js +4 -4
- package/blueprints/component-test/mocha-files/__root__/__testType__/__path__/__test__.js +7 -5
- package/blueprints/component-test/mocha-rfc-232-files/__root__/__testType__/__path__/__test__.js +4 -4
- package/blueprints/component-test/qunit-files/__root__/__testType__/__path__/__test__.js +4 -4
- package/blueprints/component-test/qunit-rfc-232-files/__root__/__testType__/__path__/__test__.js +4 -4
- package/blueprints/controller/files/__root__/__path__/__name__.js +1 -2
- package/blueprints/controller-test/mocha-0.12-files/__root__/__testType__/__path__/__test__.js +2 -2
- package/blueprints/controller-test/mocha-files/__root__/__testType__/__path__/__test__.js +5 -3
- package/blueprints/controller-test/mocha-rfc-232-files/__root__/__testType__/__path__/__test__.js +2 -2
- package/blueprints/controller-test/qunit-files/__root__/__testType__/__path__/__test__.js +1 -1
- package/blueprints/controller-test/qunit-rfc-232-files/__root__/__testType__/__path__/__test__.js +2 -2
- package/blueprints/helper/files/__root__/__collection__/__name__.js +1 -1
- package/blueprints/helper/mu-files/__root__/__collection__/__name__.js +1 -1
- package/blueprints/helper-test/mocha-0.12-files/__root__/__testType__/__collection__/__name__-test.js +3 -3
- package/blueprints/helper-test/mocha-files/__root__/__testType__/__collection__/__name__-test.js +6 -4
- package/blueprints/helper-test/mocha-rfc-232-files/__root__/__testType__/__collection__/__name__-test.js +2 -2
- package/blueprints/helper-test/qunit-files/__root__/__testType__/__collection__/__name__-test.js +2 -2
- package/blueprints/helper-test/qunit-rfc-232-files/__root__/__testType__/__collection__/__name__-test.js +2 -2
- package/blueprints/initializer/files/__root__/initializers/__name__.js +2 -3
- package/blueprints/initializer-test/mocha-files/__root__/__testType__/__path__/__name__-test.js +6 -7
- package/blueprints/initializer-test/mocha-rfc-232-files/__root__/__testType__/__path__/__name__-test.js +5 -5
- package/blueprints/initializer-test/qunit-files/__root__/__testType__/__path__/__name__-test.js +3 -4
- package/blueprints/instance-initializer/files/__root__/instance-initializers/__name__.js +2 -3
- package/blueprints/instance-initializer-test/mocha-files/__root__/__testType__/__path__/__name__-test.js +5 -5
- package/blueprints/instance-initializer-test/mocha-rfc-232-files/__root__/__testType__/__path__/__name__-test.js +5 -5
- package/blueprints/instance-initializer-test/qunit-files/__root__/__testType__/__path__/__name__-test.js +2 -2
- package/blueprints/mixin/files/__root__/mixins/__name__.js +1 -2
- package/blueprints/mixin-test/mocha-files/__root__/__testType__/__name__-test.js +2 -2
- package/blueprints/mixin-test/mocha-rfc-232-files/__root__/__testType__/__name__-test.js +2 -2
- package/blueprints/mixin-test/qunit-files/__root__/__testType__/__name__-test.js +1 -1
- package/blueprints/mixin-test/qunit-rfc-232-files/__root__/__testType__/__name__-test.js +1 -1
- package/blueprints/route/files/__root__/__path__/__name__.js +2 -2
- package/blueprints/route-test/mocha-0.12-files/__root__/__testType__/__path__/__test__.js +2 -2
- package/blueprints/route-test/mocha-files/__root__/__testType__/__path__/__test__.js +5 -3
- package/blueprints/route-test/mocha-rfc-232-files/__root__/__testType__/__path__/__test__.js +2 -2
- package/blueprints/route-test/qunit-files/__root__/__testType__/__path__/__test__.js +1 -1
- package/blueprints/route-test/qunit-rfc-232-files/__root__/__testType__/__path__/__test__.js +2 -2
- package/blueprints/service/files/__root__/__path__/__name__.js +1 -2
- package/blueprints/service-test/mocha-0.12-files/__root__/__testType__/__path__/__test__.js +2 -2
- package/blueprints/service-test/mocha-files/__root__/__testType__/__path__/__test__.js +5 -3
- package/blueprints/service-test/mocha-rfc-232-files/__root__/__testType__/__path__/__test__.js +2 -2
- package/blueprints/service-test/qunit-files/__root__/__testType__/__path__/__test__.js +1 -1
- package/blueprints/service-test/qunit-rfc-232-files/__root__/__testType__/__path__/__test__.js +2 -2
- package/blueprints/util-test/mocha-files/__root__/__testType__/__name__-test.js +2 -2
- package/blueprints/util-test/mocha-rfc-232-files/__root__/__testType__/__name__-test.js +2 -2
- package/blueprints/util-test/qunit-files/__root__/__testType__/__name__-test.js +1 -1
- package/blueprints/util-test/qunit-rfc-232-files/__root__/__testType__/__name__-test.js +2 -3
- package/build-metadata.json +3 -3
- package/dist/dependencies/router_js.js +67 -32
- package/dist/ember-template-compiler.js +1168 -908
- package/dist/ember-template-compiler.map +1 -1
- package/dist/ember-testing.js +76 -43
- package/dist/ember-testing.map +1 -1
- package/dist/ember.debug.js +3206 -2734
- package/dist/ember.debug.map +1 -1
- package/dist/header/license.js +1 -1
- package/dist/packages/@ember/-internals/container/index.js +18 -13
- package/dist/packages/@ember/-internals/glimmer/index.js +128 -67
- package/dist/packages/@ember/-internals/meta/lib/meta.js +8 -9
- package/dist/packages/@ember/-internals/metal/index.js +58 -61
- package/dist/packages/@ember/-internals/routing/lib/ext/controller.js +10 -8
- package/dist/packages/@ember/-internals/routing/lib/services/router.js +155 -191
- package/dist/packages/@ember/-internals/routing/lib/services/routing.js +2 -0
- package/dist/packages/@ember/-internals/routing/lib/system/generate_controller.js +3 -1
- package/dist/packages/@ember/-internals/routing/lib/system/route-info.js +2 -2
- package/dist/packages/@ember/-internals/routing/lib/system/route.js +108 -380
- package/dist/packages/@ember/-internals/routing/lib/system/router.js +65 -46
- package/dist/packages/@ember/-internals/routing/lib/utils.js +33 -21
- package/dist/packages/@ember/-internals/runtime/lib/mixins/action_handler.js +32 -32
- package/dist/packages/@ember/-internals/runtime/lib/mixins/container_proxy.js +29 -29
- package/dist/packages/@ember/-internals/runtime/lib/mixins/registry_proxy.js +51 -50
- package/dist/packages/@ember/-internals/utils/index.js +3 -1
- package/dist/packages/@ember/-internals/views/lib/system/utils.js +1 -0
- package/dist/packages/@ember/application/instance.js +3 -3
- package/dist/packages/@ember/canary-features/index.js +0 -10
- package/dist/packages/@ember/controller/index.js +3 -54
- package/dist/packages/@ember/debug/lib/capture-render-tree.js +2 -0
- package/dist/packages/@ember/instrumentation/index.js +9 -13
- package/dist/packages/@ember/routing/router-service.js +1 -0
- package/dist/packages/@ember/service/index.js +6 -73
- package/dist/packages/ember/index.js +3 -14
- package/dist/packages/ember/version.js +1 -1
- package/docs/data.json +556 -504
- package/package.json +13 -13
|
@@ -9,74 +9,99 @@ var __decorate = this && this.__decorate || function (decorators, target, key, d
|
|
|
9
9
|
import { privatize as P } from '@ember/-internals/container';
|
|
10
10
|
import { addObserver, computed, defineProperty, descriptorForProperty, flushAsyncObservers, get, getProperties, isEmpty, set, setProperties } from '@ember/-internals/metal';
|
|
11
11
|
import { getOwner } from '@ember/-internals/owner';
|
|
12
|
+
import { BucketCache } from '@ember/-internals/routing';
|
|
12
13
|
import { A as emberA, ActionHandler, Evented, Object as EmberObject, typeOf } from '@ember/-internals/runtime';
|
|
13
14
|
import { isProxy, lookupDescriptor, symbol } from '@ember/-internals/utils';
|
|
15
|
+
import Controller from '@ember/controller';
|
|
14
16
|
import { assert, info, isTesting } from '@ember/debug';
|
|
17
|
+
import EngineInstance from '@ember/engine/instance';
|
|
15
18
|
import { dependentKeyCompat } from '@ember/object/compat';
|
|
16
19
|
import { once } from '@ember/runloop';
|
|
17
20
|
import { DEBUG } from '@glimmer/env';
|
|
18
21
|
import { PARAMS_SYMBOL, STATE_SYMBOL } from 'router_js';
|
|
19
22
|
import { calculateCacheKey, deprecateTransitionMethods, normalizeControllerQueryParams, prefixRouteNameArg, stashParamNames } from '../utils';
|
|
20
23
|
import generateController from './generate_controller';
|
|
24
|
+
import EmberRouter from './router';
|
|
21
25
|
export const ROUTE_CONNECTIONS = new WeakMap();
|
|
22
26
|
const RENDER = symbol('render');
|
|
23
|
-
export function defaultSerialize(model, params) {
|
|
24
|
-
if (params.length < 1 || !model) {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
let object = {};
|
|
29
|
-
|
|
30
|
-
if (params.length === 1) {
|
|
31
|
-
let [name] = params;
|
|
32
|
-
|
|
33
|
-
if (name in model) {
|
|
34
|
-
object[name] = get(model, name);
|
|
35
|
-
} else if (/_id$/.test(name)) {
|
|
36
|
-
object[name] = get(model, 'id');
|
|
37
|
-
} else if (isProxy(model)) {
|
|
38
|
-
object[name] = get(model, name);
|
|
39
|
-
}
|
|
40
|
-
} else {
|
|
41
|
-
object = getProperties(model, params);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return object;
|
|
45
|
-
}
|
|
46
|
-
export function hasDefaultSerialize(route) {
|
|
47
|
-
return route.serialize === defaultSerialize;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
@module @ember/routing
|
|
51
|
-
*/
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
The `Route` class is used to define individual routes. Refer to
|
|
55
|
-
the [routing guide](https://guides.emberjs.com/release/routing/) for documentation.
|
|
56
|
-
|
|
57
|
-
@class Route
|
|
58
|
-
@extends EmberObject
|
|
59
|
-
@uses ActionHandler
|
|
60
|
-
@uses Evented
|
|
61
|
-
@since 1.0.0
|
|
62
|
-
@public
|
|
63
|
-
*/
|
|
64
27
|
|
|
65
28
|
class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
66
29
|
constructor(owner) {
|
|
67
|
-
super(
|
|
30
|
+
super(owner);
|
|
68
31
|
this.context = {};
|
|
69
32
|
|
|
70
33
|
if (owner) {
|
|
71
34
|
let router = owner.lookup('router:main');
|
|
72
35
|
let bucketCache = owner.lookup(P`-bucket-cache:main`);
|
|
73
|
-
assert('ROUTER BUG: Expected route injections to be defined on the route. This is an internal bug, please open an issue on Github if you see this message!', router && bucketCache);
|
|
36
|
+
assert('ROUTER BUG: Expected route injections to be defined on the route. This is an internal bug, please open an issue on Github if you see this message!', router instanceof EmberRouter && bucketCache instanceof BucketCache);
|
|
74
37
|
this._router = router;
|
|
75
38
|
this._bucketCache = bucketCache;
|
|
76
39
|
this._topLevelViewTemplate = owner.lookup('template:-outlet');
|
|
77
40
|
this._environment = owner.lookup('-environment:main');
|
|
78
41
|
}
|
|
79
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
A hook you can implement to convert the route's model into parameters
|
|
45
|
+
for the URL.
|
|
46
|
+
```app/router.js
|
|
47
|
+
// ...
|
|
48
|
+
Router.map(function() {
|
|
49
|
+
this.route('post', { path: '/posts/:post_id' });
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
```app/routes/post.js
|
|
53
|
+
import Route from '@ember/routing/route';
|
|
54
|
+
export default class PostRoute extends Route {
|
|
55
|
+
model({ post_id }) {
|
|
56
|
+
// the server returns `{ id: 12 }`
|
|
57
|
+
return fetch(`/posts/${post_id}`;
|
|
58
|
+
}
|
|
59
|
+
serialize(model) {
|
|
60
|
+
// this will make the URL `/posts/12`
|
|
61
|
+
return { post_id: model.id };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
The default `serialize` method will insert the model's `id` into the
|
|
66
|
+
route's dynamic segment (in this case, `:post_id`) if the segment contains '_id'.
|
|
67
|
+
If the route has multiple dynamic segments or does not contain '_id', `serialize`
|
|
68
|
+
will return `getProperties(model, params)`
|
|
69
|
+
This method is called when `transitionTo` is called with a context
|
|
70
|
+
in order to populate the URL.
|
|
71
|
+
@method serialize
|
|
72
|
+
@param {Object} model the routes model
|
|
73
|
+
@param {Array} params an Array of parameter names for the current
|
|
74
|
+
route (in the example, `['post_id']`.
|
|
75
|
+
@return {Object} the serialized parameters
|
|
76
|
+
@since 1.0.0
|
|
77
|
+
@public
|
|
78
|
+
*/
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
serialize(model, params) {
|
|
82
|
+
if (params.length < 1 || !model) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
let object = {};
|
|
87
|
+
|
|
88
|
+
if (params.length === 1) {
|
|
89
|
+
let [name] = params;
|
|
90
|
+
assert('has name', name);
|
|
91
|
+
|
|
92
|
+
if (name in model) {
|
|
93
|
+
object[name] = get(model, name);
|
|
94
|
+
} else if (/_id$/.test(name)) {
|
|
95
|
+
object[name] = get(model, 'id');
|
|
96
|
+
} else if (isProxy(model)) {
|
|
97
|
+
object[name] = get(model, name);
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
object = getProperties(model, params);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return object;
|
|
104
|
+
}
|
|
80
105
|
/**
|
|
81
106
|
Sets the name for this route, including a fully resolved name for routes
|
|
82
107
|
inside engines.
|
|
@@ -89,7 +114,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
89
114
|
_setRouteName(name) {
|
|
90
115
|
this.routeName = name;
|
|
91
116
|
let owner = getOwner(this);
|
|
92
|
-
assert('
|
|
117
|
+
assert('Expected route to have EngineInstance as owner', owner instanceof EngineInstance);
|
|
93
118
|
this.fullRouteName = getEngineRouteName(owner, name);
|
|
94
119
|
}
|
|
95
120
|
/**
|
|
@@ -118,9 +143,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
118
143
|
namePaths[a] = `${routeInfo.name}.${names[a]}`;
|
|
119
144
|
}
|
|
120
145
|
|
|
121
|
-
for (let
|
|
122
|
-
let qp = qps[i];
|
|
123
|
-
|
|
146
|
+
for (let qp of qps) {
|
|
124
147
|
if (qp.scope === 'model') {
|
|
125
148
|
qp.parts = namePaths;
|
|
126
149
|
}
|
|
@@ -203,9 +226,9 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
203
226
|
let fullName = route.fullRouteName;
|
|
204
227
|
let params = Object.assign({}, state.params[fullName]);
|
|
205
228
|
let queryParams = getQueryParamsFor(route, state);
|
|
206
|
-
return Object.
|
|
229
|
+
return Object.entries(queryParams).reduce((params, [key, value]) => {
|
|
207
230
|
assert(`The route '${this.routeName}' has both a dynamic segment and query param with name '${key}'. Please rename one to avoid collisions.`, !params[key]);
|
|
208
|
-
params[key] =
|
|
231
|
+
params[key] = value;
|
|
209
232
|
return params;
|
|
210
233
|
}, params);
|
|
211
234
|
}
|
|
@@ -322,148 +345,6 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
322
345
|
this.activate(transition);
|
|
323
346
|
this.trigger('activate', transition);
|
|
324
347
|
}
|
|
325
|
-
/**
|
|
326
|
-
The `willTransition` action is fired at the beginning of any
|
|
327
|
-
attempted transition with a `Transition` object as the sole
|
|
328
|
-
argument. This action can be used for aborting, redirecting,
|
|
329
|
-
or decorating the transition from the currently active routes.
|
|
330
|
-
A good example is preventing navigation when a form is
|
|
331
|
-
half-filled out:
|
|
332
|
-
```app/routes/contact-form.js
|
|
333
|
-
import Route from '@ember/routing/route';
|
|
334
|
-
import { action } from '@ember/object';
|
|
335
|
-
export default class ContactFormRoute extends Route {
|
|
336
|
-
@action
|
|
337
|
-
willTransition(transition) {
|
|
338
|
-
if (this.controller.get('userHasEnteredData')) {
|
|
339
|
-
this.controller.displayNavigationConfirm();
|
|
340
|
-
transition.abort();
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
```
|
|
345
|
-
You can also redirect elsewhere by calling
|
|
346
|
-
`this.transitionTo('elsewhere')` from within `willTransition`.
|
|
347
|
-
Note that `willTransition` will not be fired for the
|
|
348
|
-
redirecting `transitionTo`, since `willTransition` doesn't
|
|
349
|
-
fire when there is already a transition underway. If you want
|
|
350
|
-
subsequent `willTransition` actions to fire for the redirecting
|
|
351
|
-
transition, you must first explicitly call
|
|
352
|
-
`transition.abort()`.
|
|
353
|
-
To allow the `willTransition` event to continue bubbling to the parent
|
|
354
|
-
route, use `return true;`. When the `willTransition` method has a
|
|
355
|
-
return value of `true` then the parent route's `willTransition` method
|
|
356
|
-
will be fired, enabling "bubbling" behavior for the event.
|
|
357
|
-
@event willTransition
|
|
358
|
-
@param {Transition} transition
|
|
359
|
-
@since 1.0.0
|
|
360
|
-
@public
|
|
361
|
-
*/
|
|
362
|
-
|
|
363
|
-
/**
|
|
364
|
-
The `didTransition` action is fired after a transition has
|
|
365
|
-
successfully been completed. This occurs after the normal model
|
|
366
|
-
hooks (`beforeModel`, `model`, `afterModel`, `setupController`)
|
|
367
|
-
have resolved. The `didTransition` action has no arguments,
|
|
368
|
-
however, it can be useful for tracking page views or resetting
|
|
369
|
-
state on the controller.
|
|
370
|
-
```app/routes/login.js
|
|
371
|
-
import Route from '@ember/routing/route';
|
|
372
|
-
import { action } from '@ember/object';
|
|
373
|
-
export default class LoginRoute extends Route {
|
|
374
|
-
@action
|
|
375
|
-
didTransition() {
|
|
376
|
-
this.controller.get('errors.base').clear();
|
|
377
|
-
return true; // Bubble the didTransition event
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
```
|
|
381
|
-
@event didTransition
|
|
382
|
-
@since 1.2.0
|
|
383
|
-
@public
|
|
384
|
-
*/
|
|
385
|
-
|
|
386
|
-
/**
|
|
387
|
-
The `loading` action is fired on the route when a route's `model`
|
|
388
|
-
hook returns a promise that is not already resolved. The current
|
|
389
|
-
`Transition` object is the first parameter and the route that
|
|
390
|
-
triggered the loading event is the second parameter.
|
|
391
|
-
```app/routes/application.js
|
|
392
|
-
import Route from '@ember/routing/route';
|
|
393
|
-
import { action } from '@ember/object';
|
|
394
|
-
export default class ApplicationRoute extends Route {
|
|
395
|
-
@action
|
|
396
|
-
loading(transition, route) {
|
|
397
|
-
let controller = this.controllerFor('foo');
|
|
398
|
-
// The controller may not be instantiated when initially loading
|
|
399
|
-
if (controller) {
|
|
400
|
-
controller.currentlyLoading = true;
|
|
401
|
-
transition.finally(function() {
|
|
402
|
-
controller.currentlyLoading = false;
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
```
|
|
408
|
-
@event loading
|
|
409
|
-
@param {Transition} transition
|
|
410
|
-
@param {Route} route The route that triggered the loading event
|
|
411
|
-
@since 1.2.0
|
|
412
|
-
@public
|
|
413
|
-
*/
|
|
414
|
-
|
|
415
|
-
/**
|
|
416
|
-
When attempting to transition into a route, any of the hooks
|
|
417
|
-
may return a promise that rejects, at which point an `error`
|
|
418
|
-
action will be fired on the partially-entered routes, allowing
|
|
419
|
-
for per-route error handling logic, or shared error handling
|
|
420
|
-
logic defined on a parent route.
|
|
421
|
-
Here is an example of an error handler that will be invoked
|
|
422
|
-
for rejected promises from the various hooks on the route,
|
|
423
|
-
as well as any unhandled errors from child routes:
|
|
424
|
-
```app/routes/admin.js
|
|
425
|
-
import { reject } from 'rsvp';
|
|
426
|
-
import Route from '@ember/routing/route';
|
|
427
|
-
import { action } from '@ember/object';
|
|
428
|
-
export default class AdminRoute extends Route {
|
|
429
|
-
beforeModel() {
|
|
430
|
-
return reject('bad things!');
|
|
431
|
-
}
|
|
432
|
-
@action
|
|
433
|
-
error(error, transition) {
|
|
434
|
-
// Assuming we got here due to the error in `beforeModel`,
|
|
435
|
-
// we can expect that error === "bad things!",
|
|
436
|
-
// but a promise model rejecting would also
|
|
437
|
-
// call this hook, as would any errors encountered
|
|
438
|
-
// in `afterModel`.
|
|
439
|
-
// The `error` hook is also provided the failed
|
|
440
|
-
// `transition`, which can be stored and later
|
|
441
|
-
// `.retry()`d if desired.
|
|
442
|
-
this.transitionTo('login');
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
```
|
|
446
|
-
`error` actions that bubble up all the way to `ApplicationRoute`
|
|
447
|
-
will fire a default error handler that logs the error. You can
|
|
448
|
-
specify your own global default error handler by overriding the
|
|
449
|
-
`error` handler on `ApplicationRoute`:
|
|
450
|
-
```app/routes/application.js
|
|
451
|
-
import Route from '@ember/routing/route';
|
|
452
|
-
import { action } from '@ember/object';
|
|
453
|
-
export default class ApplicationRoute extends Route {
|
|
454
|
-
@action
|
|
455
|
-
error(error, transition) {
|
|
456
|
-
this.controllerFor('banner').displayError(error.message);
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
```
|
|
460
|
-
@event error
|
|
461
|
-
@param {Error} error
|
|
462
|
-
@param {Transition} transition
|
|
463
|
-
@since 1.0.0
|
|
464
|
-
@public
|
|
465
|
-
*/
|
|
466
|
-
|
|
467
348
|
/**
|
|
468
349
|
This event is triggered when the router enters the route. It is
|
|
469
350
|
not executed when the model for the route changes.
|
|
@@ -774,14 +655,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
774
655
|
setup(context, transition) {
|
|
775
656
|
let controllerName = this.controllerName || this.routeName;
|
|
776
657
|
let definedController = this.controllerFor(controllerName, true);
|
|
777
|
-
let controller;
|
|
778
|
-
|
|
779
|
-
if (definedController) {
|
|
780
|
-
controller = definedController;
|
|
781
|
-
} else {
|
|
782
|
-
controller = this.generateController(controllerName);
|
|
783
|
-
} // SAFETY: Since `_qp` is protected we can't infer the type
|
|
784
|
-
|
|
658
|
+
let controller = definedController !== null && definedController !== void 0 ? definedController : this.generateController(controllerName); // SAFETY: Since `_qp` is protected we can't infer the type
|
|
785
659
|
|
|
786
660
|
let queryParams = get(this, '_qp'); // Assign the route's controller so that it can more easily be
|
|
787
661
|
// referenced in action handlers. Side effects. Side effects everywhere.
|
|
@@ -803,6 +677,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
803
677
|
let allParams = queryParams.propertyNames;
|
|
804
678
|
allParams.forEach(prop => {
|
|
805
679
|
let aQp = queryParams.map[prop];
|
|
680
|
+
assert('expected aQp', aQp);
|
|
806
681
|
aQp.values = params;
|
|
807
682
|
let cacheKey = calculateCacheKey(aQp.route.fullRouteName, aQp.parts, aQp.values);
|
|
808
683
|
let value = cache.lookup(cacheKey, prop, aQp.undecoratedDefaultValue);
|
|
@@ -839,71 +714,10 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
839
714
|
let cacheKey = calculateCacheKey(qp.route.fullRouteName, qp.parts, qp.values);
|
|
840
715
|
cache.stash(cacheKey, prop, value);
|
|
841
716
|
}
|
|
842
|
-
/**
|
|
843
|
-
This hook is the first of the route entry validation hooks
|
|
844
|
-
called when an attempt is made to transition into a route
|
|
845
|
-
or one of its children. It is called before `model` and
|
|
846
|
-
`afterModel`, and is appropriate for cases when:
|
|
847
|
-
1) A decision can be made to redirect elsewhere without
|
|
848
|
-
needing to resolve the model first.
|
|
849
|
-
2) Any async operations need to occur first before the
|
|
850
|
-
model is attempted to be resolved.
|
|
851
|
-
This hook is provided the current `transition` attempt
|
|
852
|
-
as a parameter, which can be used to `.abort()` the transition,
|
|
853
|
-
save it for a later `.retry()`, or retrieve values set
|
|
854
|
-
on it from a previous hook. You can also just call
|
|
855
|
-
`this.transitionTo` to another route to implicitly
|
|
856
|
-
abort the `transition`.
|
|
857
|
-
You can return a promise from this hook to pause the
|
|
858
|
-
transition until the promise resolves (or rejects). This could
|
|
859
|
-
be useful, for instance, for retrieving async code from
|
|
860
|
-
the server that is required to enter a route.
|
|
861
|
-
@method beforeModel
|
|
862
|
-
@param {Transition} transition
|
|
863
|
-
@return {any | Promise<any>} if the value returned from this hook is
|
|
864
|
-
a promise, the transition will pause until the transition
|
|
865
|
-
resolves. Otherwise, non-promise return values are not
|
|
866
|
-
utilized in any way.
|
|
867
|
-
@since 1.0.0
|
|
868
|
-
@public
|
|
869
|
-
*/
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
beforeModel() {}
|
|
873
|
-
/**
|
|
874
|
-
This hook is called after this route's model has resolved.
|
|
875
|
-
It follows identical async/promise semantics to `beforeModel`
|
|
876
|
-
but is provided the route's resolved model in addition to
|
|
877
|
-
the `transition`, and is therefore suited to performing
|
|
878
|
-
logic that can only take place after the model has already
|
|
879
|
-
resolved.
|
|
880
|
-
```app/routes/posts.js
|
|
881
|
-
import Route from '@ember/routing/route';
|
|
882
|
-
export default class PostsRoute extends Route {
|
|
883
|
-
afterModel(posts, transition) {
|
|
884
|
-
if (posts.get('length') === 1) {
|
|
885
|
-
this.transitionTo('post.show', posts.get('firstObject'));
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
}
|
|
889
|
-
```
|
|
890
|
-
Refer to documentation for `beforeModel` for a description
|
|
891
|
-
of transition-pausing semantics when a promise is returned
|
|
892
|
-
from this hook.
|
|
893
|
-
@method afterModel
|
|
894
|
-
@param {Object} resolvedModel the value returned from `model`,
|
|
895
|
-
or its resolved value if it was a promise
|
|
896
|
-
@param {Transition} transition
|
|
897
|
-
@return {any | Promise<any>} if the value returned from this hook is
|
|
898
|
-
a promise, the transition will pause until the transition
|
|
899
|
-
resolves. Otherwise, non-promise return values are not
|
|
900
|
-
utilized in any way.
|
|
901
|
-
@since 1.0.0
|
|
902
|
-
@public
|
|
903
|
-
*/
|
|
904
717
|
|
|
718
|
+
beforeModel(_transition) {}
|
|
905
719
|
|
|
906
|
-
afterModel() {}
|
|
720
|
+
afterModel(_resolvedModel, _transition) {}
|
|
907
721
|
/**
|
|
908
722
|
A hook you can implement to optionally redirect to another route.
|
|
909
723
|
Calling `this.transitionTo` from inside of the `redirect` hook will
|
|
@@ -926,7 +740,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
926
740
|
*/
|
|
927
741
|
|
|
928
742
|
|
|
929
|
-
redirect() {}
|
|
743
|
+
redirect(_model, _transition) {}
|
|
930
744
|
/**
|
|
931
745
|
Called when the context is changed by router.js.
|
|
932
746
|
@private
|
|
@@ -1021,11 +835,13 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1021
835
|
|
|
1022
836
|
if (!name) {
|
|
1023
837
|
if (sawParams) {
|
|
838
|
+
// SAFETY: This should be equivalent
|
|
1024
839
|
return Object.assign({}, params);
|
|
1025
840
|
} else {
|
|
1026
841
|
if (transition.resolveIndex < 1) {
|
|
1027
842
|
return;
|
|
1028
|
-
}
|
|
843
|
+
} // SAFETY: This should be correct, but TS is unable to infer this.
|
|
844
|
+
|
|
1029
845
|
|
|
1030
846
|
return transition[STATE_SYMBOL].routeInfos[transition.resolveIndex - 1].context;
|
|
1031
847
|
}
|
|
@@ -1116,29 +932,8 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1116
932
|
set(controller, 'model', context);
|
|
1117
933
|
}
|
|
1118
934
|
}
|
|
1119
|
-
/**
|
|
1120
|
-
Returns the controller of the current route, or a parent (or any ancestor)
|
|
1121
|
-
route in a route hierarchy.
|
|
1122
|
-
The controller instance must already have been created, either through entering the
|
|
1123
|
-
associated route or using `generateController`.
|
|
1124
|
-
```app/routes/post.js
|
|
1125
|
-
import Route from '@ember/routing/route';
|
|
1126
|
-
export default class PostRoute extends Route {
|
|
1127
|
-
setupController(controller, post) {
|
|
1128
|
-
super.setupController(controller, post);
|
|
1129
|
-
this.controllerFor('posts').set('currentPost', post);
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
```
|
|
1133
|
-
@method controllerFor
|
|
1134
|
-
@param {String} name the name of the route or controller
|
|
1135
|
-
@return {Controller}
|
|
1136
|
-
@since 1.0.0
|
|
1137
|
-
@public
|
|
1138
|
-
*/
|
|
1139
|
-
|
|
1140
935
|
|
|
1141
|
-
controllerFor(name, _skipAssert) {
|
|
936
|
+
controllerFor(name, _skipAssert = false) {
|
|
1142
937
|
let owner = getOwner(this);
|
|
1143
938
|
assert('Route is unexpectedly missing an owner', owner);
|
|
1144
939
|
let route = owner.lookup(`route:${name}`);
|
|
@@ -1152,6 +947,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1152
947
|
// passed a model to skip the assertion.
|
|
1153
948
|
|
|
1154
949
|
assert(`The controller named '${name}' could not be found. Make sure that this route exists and has already been entered at least once. If you are accessing a controller not associated with a route, make sure the controller class is explicitly defined.`, controller !== undefined || _skipAssert === true);
|
|
950
|
+
assert(`Expected controller:${name} to be an instance of Controller`, controller === undefined || controller instanceof Controller);
|
|
1155
951
|
return controller;
|
|
1156
952
|
}
|
|
1157
953
|
/**
|
|
@@ -1216,7 +1012,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1216
1012
|
modelFor(_name) {
|
|
1217
1013
|
let name;
|
|
1218
1014
|
let owner = getOwner(this);
|
|
1219
|
-
assert('
|
|
1015
|
+
assert('Expected router owner to be an EngineInstance', owner instanceof EngineInstance);
|
|
1220
1016
|
let transition = this._router && this._router._routerMicrolib ? this._router._routerMicrolib.activeTransition : undefined; // Only change the route name when there is an active transition.
|
|
1221
1017
|
// Otherwise, use the passed in route name.
|
|
1222
1018
|
|
|
@@ -1237,7 +1033,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1237
1033
|
}
|
|
1238
1034
|
}
|
|
1239
1035
|
|
|
1240
|
-
return route
|
|
1036
|
+
return route === null || route === void 0 ? void 0 : route.currentModel;
|
|
1241
1037
|
}
|
|
1242
1038
|
/**
|
|
1243
1039
|
`this[RENDER]` is used to render a template into a region of another template
|
|
@@ -1280,39 +1076,6 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1280
1076
|
once(this._router, '_setOutlets');
|
|
1281
1077
|
}
|
|
1282
1078
|
}
|
|
1283
|
-
/**
|
|
1284
|
-
Allows you to produce custom metadata for the route.
|
|
1285
|
-
The return value of this method will be attached to
|
|
1286
|
-
its corresponding RouteInfoWithAttributes object.
|
|
1287
|
-
Example
|
|
1288
|
-
```app/routes/posts/index.js
|
|
1289
|
-
import Route from '@ember/routing/route';
|
|
1290
|
-
export default class PostsIndexRoute extends Route {
|
|
1291
|
-
buildRouteInfoMetadata() {
|
|
1292
|
-
return { title: 'Posts Page' }
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
```
|
|
1296
|
-
```app/routes/application.js
|
|
1297
|
-
import Route from '@ember/routing/route';
|
|
1298
|
-
import { service } from '@ember/service';
|
|
1299
|
-
export default class ApplicationRoute extends Route {
|
|
1300
|
-
@service router
|
|
1301
|
-
constructor() {
|
|
1302
|
-
super(...arguments);
|
|
1303
|
-
this.router.on('routeDidChange', transition => {
|
|
1304
|
-
document.title = transition.to.metadata.title;
|
|
1305
|
-
// would update document's title to "Posts Page"
|
|
1306
|
-
});
|
|
1307
|
-
}
|
|
1308
|
-
}
|
|
1309
|
-
```
|
|
1310
|
-
@method buildRouteInfoMetadata
|
|
1311
|
-
@return any
|
|
1312
|
-
@since 3.10.0
|
|
1313
|
-
@public
|
|
1314
|
-
*/
|
|
1315
|
-
|
|
1316
1079
|
|
|
1317
1080
|
buildRouteInfoMetadata() {}
|
|
1318
1081
|
|
|
@@ -1377,11 +1140,12 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1377
1140
|
let hasRouterDefinedQueryParams = Object.keys(queryParameterConfiguraton).length > 0;
|
|
1378
1141
|
|
|
1379
1142
|
if (controller) {
|
|
1380
|
-
// the developer has authored a controller class in their application for
|
|
1143
|
+
assert('Expected an instance of controller', controller instanceof Controller); // the developer has authored a controller class in their application for
|
|
1381
1144
|
// this route find its query params and normalize their object shape them
|
|
1382
1145
|
// merge in the query params for the route. As a mergedProperty,
|
|
1383
1146
|
// Route#queryParams is always at least `{}`
|
|
1384
|
-
|
|
1147
|
+
|
|
1148
|
+
let controllerDefinedQueryParameterConfiguration = get(controller, 'queryParams') || [];
|
|
1385
1149
|
let normalizedControllerQueryParameterConfiguration = normalizeControllerQueryParams(controllerDefinedQueryParameterConfiguration);
|
|
1386
1150
|
combinedQueryParameterConfiguration = mergeEachQueryParams(normalizedControllerQueryParameterConfiguration, queryParameterConfiguraton);
|
|
1387
1151
|
} else if (hasRouterDefinedQueryParams) {
|
|
@@ -1453,6 +1217,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1453
1217
|
*/
|
|
1454
1218
|
inactive: (prop, value) => {
|
|
1455
1219
|
let qp = map[prop];
|
|
1220
|
+
assert('expected inactive callback to only be called for registered qps', qp);
|
|
1456
1221
|
|
|
1457
1222
|
this._qpChanged(prop, value, qp);
|
|
1458
1223
|
},
|
|
@@ -1464,6 +1229,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1464
1229
|
*/
|
|
1465
1230
|
active: (prop, value) => {
|
|
1466
1231
|
let qp = map[prop];
|
|
1232
|
+
assert('expected active callback to only be called for registered qps', qp);
|
|
1467
1233
|
|
|
1468
1234
|
this._qpChanged(prop, value, qp);
|
|
1469
1235
|
|
|
@@ -1476,6 +1242,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1476
1242
|
*/
|
|
1477
1243
|
allowOverrides: (prop, value) => {
|
|
1478
1244
|
let qp = map[prop];
|
|
1245
|
+
assert('expected allowOverrides callback to only be called for registered qps', qp);
|
|
1479
1246
|
|
|
1480
1247
|
this._qpChanged(prop, value, qp);
|
|
1481
1248
|
|
|
@@ -1506,7 +1273,9 @@ function routeInfoFor(route, routeInfos, offset = 0) {
|
|
|
1506
1273
|
let current;
|
|
1507
1274
|
|
|
1508
1275
|
for (let i = 0; i < routeInfos.length; i++) {
|
|
1509
|
-
|
|
1276
|
+
let routeInfo = routeInfos[i];
|
|
1277
|
+
assert('has current routeInfo', routeInfo);
|
|
1278
|
+
current = routeInfo.route;
|
|
1510
1279
|
|
|
1511
1280
|
if (current === route) {
|
|
1512
1281
|
return routeInfos[i + offset];
|
|
@@ -1535,7 +1304,7 @@ function buildRenderOptions(route, nameOrOptions, options) {
|
|
|
1535
1304
|
let owner = getOwner(route);
|
|
1536
1305
|
assert('Route is unexpectedly missing an owner', owner);
|
|
1537
1306
|
let name, templateName, into, outlet, model;
|
|
1538
|
-
let controller
|
|
1307
|
+
let controller;
|
|
1539
1308
|
|
|
1540
1309
|
if (options) {
|
|
1541
1310
|
into = options.into && options.into.replace(/\//g, '.');
|
|
@@ -1568,6 +1337,8 @@ function buildRenderOptions(route, nameOrOptions, options) {
|
|
|
1568
1337
|
assert(`You passed \`controller: '${controllerName}'\` into the \`render\` method, but no such controller could be found.`, isDefaultRender || controller !== undefined);
|
|
1569
1338
|
}
|
|
1570
1339
|
|
|
1340
|
+
assert('Expected an instance of controller', controller instanceof Controller);
|
|
1341
|
+
|
|
1571
1342
|
if (model === undefined) {
|
|
1572
1343
|
model = route.currentModel;
|
|
1573
1344
|
} else {
|
|
@@ -1628,9 +1399,10 @@ export function getFullQueryParams(router, state) {
|
|
|
1628
1399
|
function getQueryParamsFor(route, state) {
|
|
1629
1400
|
state.queryParamsFor = state.queryParamsFor || {};
|
|
1630
1401
|
let name = route.fullRouteName;
|
|
1402
|
+
let existing = state.queryParamsFor[name];
|
|
1631
1403
|
|
|
1632
|
-
if (
|
|
1633
|
-
return
|
|
1404
|
+
if (existing) {
|
|
1405
|
+
return existing;
|
|
1634
1406
|
}
|
|
1635
1407
|
|
|
1636
1408
|
let fullQueryParams = getFullQueryParams(route._router, state);
|
|
@@ -1639,9 +1411,8 @@ function getQueryParamsFor(route, state) {
|
|
|
1639
1411
|
|
|
1640
1412
|
let qps = get(route, '_qp').qps;
|
|
1641
1413
|
|
|
1642
|
-
for (let
|
|
1414
|
+
for (let qp of qps) {
|
|
1643
1415
|
// Put deserialized qp on params hash.
|
|
1644
|
-
let qp = qps[i];
|
|
1645
1416
|
let qpValueWasPassedIn = (qp.prop in fullQueryParams);
|
|
1646
1417
|
params[qp.prop] = qpValueWasPassedIn ? fullQueryParams[qp.prop] : copyDefaultValue(qp.defaultValue);
|
|
1647
1418
|
}
|
|
@@ -1732,54 +1503,12 @@ function getEngineRouteName(engine, routeName) {
|
|
|
1732
1503
|
|
|
1733
1504
|
return routeName;
|
|
1734
1505
|
}
|
|
1735
|
-
/**
|
|
1736
|
-
A hook you can implement to convert the route's model into parameters
|
|
1737
|
-
for the URL.
|
|
1738
|
-
|
|
1739
|
-
```app/router.js
|
|
1740
|
-
// ...
|
|
1741
|
-
|
|
1742
|
-
Router.map(function() {
|
|
1743
|
-
this.route('post', { path: '/posts/:post_id' });
|
|
1744
|
-
});
|
|
1745
1506
|
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
export default class PostRoute extends Route {
|
|
1752
|
-
model({ post_id }) {
|
|
1753
|
-
// the server returns `{ id: 12 }`
|
|
1754
|
-
return fetch(`/posts/${post_id}`;
|
|
1755
|
-
}
|
|
1756
|
-
|
|
1757
|
-
serialize(model) {
|
|
1758
|
-
// this will make the URL `/posts/12`
|
|
1759
|
-
return { post_id: model.id };
|
|
1760
|
-
}
|
|
1761
|
-
}
|
|
1762
|
-
```
|
|
1763
|
-
|
|
1764
|
-
The default `serialize` method will insert the model's `id` into the
|
|
1765
|
-
route's dynamic segment (in this case, `:post_id`) if the segment contains '_id'.
|
|
1766
|
-
If the route has multiple dynamic segments or does not contain '_id', `serialize`
|
|
1767
|
-
will return `getProperties(model, params)`
|
|
1768
|
-
|
|
1769
|
-
This method is called when `transitionTo` is called with a context
|
|
1770
|
-
in order to populate the URL.
|
|
1771
|
-
|
|
1772
|
-
@method serialize
|
|
1773
|
-
@param {Object} model the routes model
|
|
1774
|
-
@param {Array} params an Array of parameter names for the current
|
|
1775
|
-
route (in the example, `['post_id']`.
|
|
1776
|
-
@return {Object} the serialized parameters
|
|
1777
|
-
@since 1.0.0
|
|
1778
|
-
@public
|
|
1779
|
-
*/
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
Route.prototype.serialize = defaultSerialize; // Set these here so they can be overridden with extend
|
|
1507
|
+
const defaultSerialize = Route.prototype.serialize;
|
|
1508
|
+
export { defaultSerialize };
|
|
1509
|
+
export function hasDefaultSerialize(route) {
|
|
1510
|
+
return route.serialize === defaultSerialize;
|
|
1511
|
+
} // Set these here so they can be overridden with extend
|
|
1783
1512
|
|
|
1784
1513
|
Route.reopen({
|
|
1785
1514
|
mergedProperties: ['queryParams'],
|
|
@@ -1842,8 +1571,8 @@ Route.reopen({
|
|
|
1842
1571
|
let qpMap = get(this, '_qp').map;
|
|
1843
1572
|
let totalChanged = Object.keys(changed).concat(Object.keys(removed));
|
|
1844
1573
|
|
|
1845
|
-
for (let
|
|
1846
|
-
let qp = qpMap[
|
|
1574
|
+
for (let change of totalChanged) {
|
|
1575
|
+
let qp = qpMap[change];
|
|
1847
1576
|
|
|
1848
1577
|
if (qp) {
|
|
1849
1578
|
let options = this._optionsForQueryParam(qp);
|
|
@@ -1880,8 +1609,7 @@ Route.reopen({
|
|
|
1880
1609
|
let replaceUrl;
|
|
1881
1610
|
stashParamNames(router, routeInfos);
|
|
1882
1611
|
|
|
1883
|
-
for (let
|
|
1884
|
-
let qp = qpMeta.qps[i];
|
|
1612
|
+
for (let qp of qpMeta.qps) {
|
|
1885
1613
|
let route = qp.route;
|
|
1886
1614
|
let controller = route.controller;
|
|
1887
1615
|
let presentKey = qp.urlKey in params && qp.urlKey; // Do a reverse lookup to see if the changed query
|