ember-source 4.3.0-alpha.2 → 4.4.0-alpha.1
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/build-metadata.json +3 -3
- package/dist/dependencies/router_js.js +66 -31
- package/dist/ember-template-compiler.js +1169 -779
- package/dist/ember-template-compiler.map +1 -1
- package/dist/ember-testing.js +74 -43
- package/dist/ember-testing.map +1 -1
- package/dist/ember.debug.js +3290 -2760
- package/dist/ember.debug.map +1 -1
- package/dist/header/license.js +1 -1
- package/dist/packages/@ember/-internals/container/index.js +15 -11
- package/dist/packages/@ember/-internals/extension-support/lib/container_debug_adapter.js +3 -3
- package/dist/packages/@ember/-internals/extension-support/lib/data_adapter.js +52 -52
- package/dist/packages/@ember/-internals/glimmer/index.js +139 -103
- package/dist/packages/@ember/-internals/meta/lib/meta.js +8 -9
- package/dist/packages/@ember/-internals/metal/index.js +44 -45
- package/dist/packages/@ember/-internals/routing/lib/ext/controller.js +10 -8
- package/dist/packages/@ember/-internals/routing/lib/location/auto_location.js +3 -1
- package/dist/packages/@ember/-internals/routing/lib/services/router.js +155 -190
- package/dist/packages/@ember/-internals/routing/lib/services/routing.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 +110 -378
- package/dist/packages/@ember/-internals/routing/lib/system/router.js +74 -36
- package/dist/packages/@ember/-internals/routing/lib/utils.js +33 -21
- package/dist/packages/@ember/-internals/runtime/lib/mixins/-proxy.js +1 -1
- package/dist/packages/@ember/-internals/runtime/lib/mixins/array.js +1 -0
- package/dist/packages/@ember/-internals/runtime/lib/mixins/comparable.js +4 -4
- package/dist/packages/@ember/-internals/runtime/lib/mixins/container_proxy.js +29 -29
- package/dist/packages/@ember/-internals/runtime/lib/mixins/promise_proxy.js +16 -16
- package/dist/packages/@ember/-internals/runtime/lib/mixins/registry_proxy.js +48 -48
- package/dist/packages/@ember/-internals/runtime/lib/mixins/target_action_support.js +8 -8
- package/dist/packages/@ember/-internals/runtime/lib/system/namespace.js +1 -2
- package/dist/packages/@ember/-internals/runtime/lib/type-of.js +1 -1
- package/dist/packages/@ember/-internals/utils/index.js +10 -8
- package/dist/packages/@ember/-internals/views/lib/system/utils.js +2 -0
- package/dist/packages/@ember/array/index.js +1 -1
- package/dist/packages/@ember/controller/index.js +3 -54
- package/dist/packages/@ember/instrumentation/index.js +9 -13
- package/dist/packages/@ember/object/compat.js +16 -7
- package/dist/packages/@ember/routing/router-service.js +1 -0
- package/dist/packages/@ember/service/index.js +6 -73
- package/dist/packages/ember/version.js +1 -1
- package/docs/data.json +571 -521
- package/package.json +13 -13
|
@@ -20,47 +20,6 @@ import { calculateCacheKey, deprecateTransitionMethods, normalizeControllerQuery
|
|
|
20
20
|
import generateController from './generate_controller';
|
|
21
21
|
export const ROUTE_CONNECTIONS = new WeakMap();
|
|
22
22
|
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
23
|
|
|
65
24
|
class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
66
25
|
constructor(owner) {
|
|
@@ -77,6 +36,68 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
77
36
|
this._environment = owner.lookup('-environment:main');
|
|
78
37
|
}
|
|
79
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
A hook you can implement to convert the route's model into parameters
|
|
41
|
+
for the URL.
|
|
42
|
+
```app/router.js
|
|
43
|
+
// ...
|
|
44
|
+
Router.map(function() {
|
|
45
|
+
this.route('post', { path: '/posts/:post_id' });
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
```app/routes/post.js
|
|
49
|
+
import Route from '@ember/routing/route';
|
|
50
|
+
export default class PostRoute extends Route {
|
|
51
|
+
model({ post_id }) {
|
|
52
|
+
// the server returns `{ id: 12 }`
|
|
53
|
+
return fetch(`/posts/${post_id}`;
|
|
54
|
+
}
|
|
55
|
+
serialize(model) {
|
|
56
|
+
// this will make the URL `/posts/12`
|
|
57
|
+
return { post_id: model.id };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
The default `serialize` method will insert the model's `id` into the
|
|
62
|
+
route's dynamic segment (in this case, `:post_id`) if the segment contains '_id'.
|
|
63
|
+
If the route has multiple dynamic segments or does not contain '_id', `serialize`
|
|
64
|
+
will return `getProperties(model, params)`
|
|
65
|
+
This method is called when `transitionTo` is called with a context
|
|
66
|
+
in order to populate the URL.
|
|
67
|
+
@method serialize
|
|
68
|
+
@param {Object} model the routes model
|
|
69
|
+
@param {Array} params an Array of parameter names for the current
|
|
70
|
+
route (in the example, `['post_id']`.
|
|
71
|
+
@return {Object} the serialized parameters
|
|
72
|
+
@since 1.0.0
|
|
73
|
+
@public
|
|
74
|
+
*/
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
serialize(model, params) {
|
|
78
|
+
if (params.length < 1 || !model) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let object = {};
|
|
83
|
+
|
|
84
|
+
if (params.length === 1) {
|
|
85
|
+
let [name] = params;
|
|
86
|
+
assert('has name', name);
|
|
87
|
+
|
|
88
|
+
if (name in model) {
|
|
89
|
+
object[name] = get(model, name);
|
|
90
|
+
} else if (/_id$/.test(name)) {
|
|
91
|
+
object[name] = get(model, 'id');
|
|
92
|
+
} else if (isProxy(model)) {
|
|
93
|
+
object[name] = get(model, name);
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
object = getProperties(model, params);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return object;
|
|
100
|
+
}
|
|
80
101
|
/**
|
|
81
102
|
Sets the name for this route, including a fully resolved name for routes
|
|
82
103
|
inside engines.
|
|
@@ -88,7 +109,9 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
88
109
|
|
|
89
110
|
_setRouteName(name) {
|
|
90
111
|
this.routeName = name;
|
|
91
|
-
|
|
112
|
+
let owner = getOwner(this);
|
|
113
|
+
assert('Route is unexpectedly missing an owner', owner);
|
|
114
|
+
this.fullRouteName = getEngineRouteName(owner, name);
|
|
92
115
|
}
|
|
93
116
|
/**
|
|
94
117
|
@private
|
|
@@ -116,9 +139,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
116
139
|
namePaths[a] = `${routeInfo.name}.${names[a]}`;
|
|
117
140
|
}
|
|
118
141
|
|
|
119
|
-
for (let
|
|
120
|
-
let qp = qps[i];
|
|
121
|
-
|
|
142
|
+
for (let qp of qps) {
|
|
122
143
|
if (qp.scope === 'model') {
|
|
123
144
|
qp.parts = namePaths;
|
|
124
145
|
}
|
|
@@ -188,7 +209,9 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
188
209
|
|
|
189
210
|
|
|
190
211
|
paramsFor(name) {
|
|
191
|
-
let
|
|
212
|
+
let owner = getOwner(this);
|
|
213
|
+
assert('Route is unexpectedly missing an owner', owner);
|
|
214
|
+
let route = owner.lookup(`route:${name}`);
|
|
192
215
|
|
|
193
216
|
if (route === undefined) {
|
|
194
217
|
return {};
|
|
@@ -199,9 +222,9 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
199
222
|
let fullName = route.fullRouteName;
|
|
200
223
|
let params = Object.assign({}, state.params[fullName]);
|
|
201
224
|
let queryParams = getQueryParamsFor(route, state);
|
|
202
|
-
return Object.
|
|
225
|
+
return Object.entries(queryParams).reduce((params, [key, value]) => {
|
|
203
226
|
assert(`The route '${this.routeName}' has both a dynamic segment and query param with name '${key}'. Please rename one to avoid collisions.`, !params[key]);
|
|
204
|
-
params[key] =
|
|
227
|
+
params[key] = value;
|
|
205
228
|
return params;
|
|
206
229
|
}, params);
|
|
207
230
|
}
|
|
@@ -318,148 +341,6 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
318
341
|
this.activate(transition);
|
|
319
342
|
this.trigger('activate', transition);
|
|
320
343
|
}
|
|
321
|
-
/**
|
|
322
|
-
The `willTransition` action is fired at the beginning of any
|
|
323
|
-
attempted transition with a `Transition` object as the sole
|
|
324
|
-
argument. This action can be used for aborting, redirecting,
|
|
325
|
-
or decorating the transition from the currently active routes.
|
|
326
|
-
A good example is preventing navigation when a form is
|
|
327
|
-
half-filled out:
|
|
328
|
-
```app/routes/contact-form.js
|
|
329
|
-
import Route from '@ember/routing/route';
|
|
330
|
-
import { action } from '@ember/object';
|
|
331
|
-
export default class ContactFormRoute extends Route {
|
|
332
|
-
@action
|
|
333
|
-
willTransition(transition) {
|
|
334
|
-
if (this.controller.get('userHasEnteredData')) {
|
|
335
|
-
this.controller.displayNavigationConfirm();
|
|
336
|
-
transition.abort();
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
```
|
|
341
|
-
You can also redirect elsewhere by calling
|
|
342
|
-
`this.transitionTo('elsewhere')` from within `willTransition`.
|
|
343
|
-
Note that `willTransition` will not be fired for the
|
|
344
|
-
redirecting `transitionTo`, since `willTransition` doesn't
|
|
345
|
-
fire when there is already a transition underway. If you want
|
|
346
|
-
subsequent `willTransition` actions to fire for the redirecting
|
|
347
|
-
transition, you must first explicitly call
|
|
348
|
-
`transition.abort()`.
|
|
349
|
-
To allow the `willTransition` event to continue bubbling to the parent
|
|
350
|
-
route, use `return true;`. When the `willTransition` method has a
|
|
351
|
-
return value of `true` then the parent route's `willTransition` method
|
|
352
|
-
will be fired, enabling "bubbling" behavior for the event.
|
|
353
|
-
@event willTransition
|
|
354
|
-
@param {Transition} transition
|
|
355
|
-
@since 1.0.0
|
|
356
|
-
@public
|
|
357
|
-
*/
|
|
358
|
-
|
|
359
|
-
/**
|
|
360
|
-
The `didTransition` action is fired after a transition has
|
|
361
|
-
successfully been completed. This occurs after the normal model
|
|
362
|
-
hooks (`beforeModel`, `model`, `afterModel`, `setupController`)
|
|
363
|
-
have resolved. The `didTransition` action has no arguments,
|
|
364
|
-
however, it can be useful for tracking page views or resetting
|
|
365
|
-
state on the controller.
|
|
366
|
-
```app/routes/login.js
|
|
367
|
-
import Route from '@ember/routing/route';
|
|
368
|
-
import { action } from '@ember/object';
|
|
369
|
-
export default class LoginRoute extends Route {
|
|
370
|
-
@action
|
|
371
|
-
didTransition() {
|
|
372
|
-
this.controller.get('errors.base').clear();
|
|
373
|
-
return true; // Bubble the didTransition event
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
```
|
|
377
|
-
@event didTransition
|
|
378
|
-
@since 1.2.0
|
|
379
|
-
@public
|
|
380
|
-
*/
|
|
381
|
-
|
|
382
|
-
/**
|
|
383
|
-
The `loading` action is fired on the route when a route's `model`
|
|
384
|
-
hook returns a promise that is not already resolved. The current
|
|
385
|
-
`Transition` object is the first parameter and the route that
|
|
386
|
-
triggered the loading event is the second parameter.
|
|
387
|
-
```app/routes/application.js
|
|
388
|
-
import Route from '@ember/routing/route';
|
|
389
|
-
import { action } from '@ember/object';
|
|
390
|
-
export default class ApplicationRoute extends Route {
|
|
391
|
-
@action
|
|
392
|
-
loading(transition, route) {
|
|
393
|
-
let controller = this.controllerFor('foo');
|
|
394
|
-
// The controller may not be instantiated when initially loading
|
|
395
|
-
if (controller) {
|
|
396
|
-
controller.currentlyLoading = true;
|
|
397
|
-
transition.finally(function() {
|
|
398
|
-
controller.currentlyLoading = false;
|
|
399
|
-
});
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
```
|
|
404
|
-
@event loading
|
|
405
|
-
@param {Transition} transition
|
|
406
|
-
@param {Route} route The route that triggered the loading event
|
|
407
|
-
@since 1.2.0
|
|
408
|
-
@public
|
|
409
|
-
*/
|
|
410
|
-
|
|
411
|
-
/**
|
|
412
|
-
When attempting to transition into a route, any of the hooks
|
|
413
|
-
may return a promise that rejects, at which point an `error`
|
|
414
|
-
action will be fired on the partially-entered routes, allowing
|
|
415
|
-
for per-route error handling logic, or shared error handling
|
|
416
|
-
logic defined on a parent route.
|
|
417
|
-
Here is an example of an error handler that will be invoked
|
|
418
|
-
for rejected promises from the various hooks on the route,
|
|
419
|
-
as well as any unhandled errors from child routes:
|
|
420
|
-
```app/routes/admin.js
|
|
421
|
-
import { reject } from 'rsvp';
|
|
422
|
-
import Route from '@ember/routing/route';
|
|
423
|
-
import { action } from '@ember/object';
|
|
424
|
-
export default class AdminRoute extends Route {
|
|
425
|
-
beforeModel() {
|
|
426
|
-
return reject('bad things!');
|
|
427
|
-
}
|
|
428
|
-
@action
|
|
429
|
-
error(error, transition) {
|
|
430
|
-
// Assuming we got here due to the error in `beforeModel`,
|
|
431
|
-
// we can expect that error === "bad things!",
|
|
432
|
-
// but a promise model rejecting would also
|
|
433
|
-
// call this hook, as would any errors encountered
|
|
434
|
-
// in `afterModel`.
|
|
435
|
-
// The `error` hook is also provided the failed
|
|
436
|
-
// `transition`, which can be stored and later
|
|
437
|
-
// `.retry()`d if desired.
|
|
438
|
-
this.transitionTo('login');
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
```
|
|
442
|
-
`error` actions that bubble up all the way to `ApplicationRoute`
|
|
443
|
-
will fire a default error handler that logs the error. You can
|
|
444
|
-
specify your own global default error handler by overriding the
|
|
445
|
-
`error` handler on `ApplicationRoute`:
|
|
446
|
-
```app/routes/application.js
|
|
447
|
-
import Route from '@ember/routing/route';
|
|
448
|
-
import { action } from '@ember/object';
|
|
449
|
-
export default class ApplicationRoute extends Route {
|
|
450
|
-
@action
|
|
451
|
-
error(error, transition) {
|
|
452
|
-
this.controllerFor('banner').displayError(error.message);
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
```
|
|
456
|
-
@event error
|
|
457
|
-
@param {Error} error
|
|
458
|
-
@param {Transition} transition
|
|
459
|
-
@since 1.0.0
|
|
460
|
-
@public
|
|
461
|
-
*/
|
|
462
|
-
|
|
463
344
|
/**
|
|
464
345
|
This event is triggered when the router enters the route. It is
|
|
465
346
|
not executed when the model for the route changes.
|
|
@@ -770,14 +651,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
770
651
|
setup(context, transition) {
|
|
771
652
|
let controllerName = this.controllerName || this.routeName;
|
|
772
653
|
let definedController = this.controllerFor(controllerName, true);
|
|
773
|
-
let controller;
|
|
774
|
-
|
|
775
|
-
if (definedController) {
|
|
776
|
-
controller = definedController;
|
|
777
|
-
} else {
|
|
778
|
-
controller = this.generateController(controllerName);
|
|
779
|
-
} // SAFETY: Since `_qp` is protected we can't infer the type
|
|
780
|
-
|
|
654
|
+
let controller = definedController !== null && definedController !== void 0 ? definedController : this.generateController(controllerName); // SAFETY: Since `_qp` is protected we can't infer the type
|
|
781
655
|
|
|
782
656
|
let queryParams = get(this, '_qp'); // Assign the route's controller so that it can more easily be
|
|
783
657
|
// referenced in action handlers. Side effects. Side effects everywhere.
|
|
@@ -799,6 +673,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
799
673
|
let allParams = queryParams.propertyNames;
|
|
800
674
|
allParams.forEach(prop => {
|
|
801
675
|
let aQp = queryParams.map[prop];
|
|
676
|
+
assert('expected aQp', aQp);
|
|
802
677
|
aQp.values = params;
|
|
803
678
|
let cacheKey = calculateCacheKey(aQp.route.fullRouteName, aQp.parts, aQp.values);
|
|
804
679
|
let value = cache.lookup(cacheKey, prop, aQp.undecoratedDefaultValue);
|
|
@@ -835,71 +710,10 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
835
710
|
let cacheKey = calculateCacheKey(qp.route.fullRouteName, qp.parts, qp.values);
|
|
836
711
|
cache.stash(cacheKey, prop, value);
|
|
837
712
|
}
|
|
838
|
-
/**
|
|
839
|
-
This hook is the first of the route entry validation hooks
|
|
840
|
-
called when an attempt is made to transition into a route
|
|
841
|
-
or one of its children. It is called before `model` and
|
|
842
|
-
`afterModel`, and is appropriate for cases when:
|
|
843
|
-
1) A decision can be made to redirect elsewhere without
|
|
844
|
-
needing to resolve the model first.
|
|
845
|
-
2) Any async operations need to occur first before the
|
|
846
|
-
model is attempted to be resolved.
|
|
847
|
-
This hook is provided the current `transition` attempt
|
|
848
|
-
as a parameter, which can be used to `.abort()` the transition,
|
|
849
|
-
save it for a later `.retry()`, or retrieve values set
|
|
850
|
-
on it from a previous hook. You can also just call
|
|
851
|
-
`this.transitionTo` to another route to implicitly
|
|
852
|
-
abort the `transition`.
|
|
853
|
-
You can return a promise from this hook to pause the
|
|
854
|
-
transition until the promise resolves (or rejects). This could
|
|
855
|
-
be useful, for instance, for retrieving async code from
|
|
856
|
-
the server that is required to enter a route.
|
|
857
|
-
@method beforeModel
|
|
858
|
-
@param {Transition} transition
|
|
859
|
-
@return {any | Promise<any>} if the value returned from this hook is
|
|
860
|
-
a promise, the transition will pause until the transition
|
|
861
|
-
resolves. Otherwise, non-promise return values are not
|
|
862
|
-
utilized in any way.
|
|
863
|
-
@since 1.0.0
|
|
864
|
-
@public
|
|
865
|
-
*/
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
beforeModel() {}
|
|
869
|
-
/**
|
|
870
|
-
This hook is called after this route's model has resolved.
|
|
871
|
-
It follows identical async/promise semantics to `beforeModel`
|
|
872
|
-
but is provided the route's resolved model in addition to
|
|
873
|
-
the `transition`, and is therefore suited to performing
|
|
874
|
-
logic that can only take place after the model has already
|
|
875
|
-
resolved.
|
|
876
|
-
```app/routes/posts.js
|
|
877
|
-
import Route from '@ember/routing/route';
|
|
878
|
-
export default class PostsRoute extends Route {
|
|
879
|
-
afterModel(posts, transition) {
|
|
880
|
-
if (posts.get('length') === 1) {
|
|
881
|
-
this.transitionTo('post.show', posts.get('firstObject'));
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
}
|
|
885
|
-
```
|
|
886
|
-
Refer to documentation for `beforeModel` for a description
|
|
887
|
-
of transition-pausing semantics when a promise is returned
|
|
888
|
-
from this hook.
|
|
889
|
-
@method afterModel
|
|
890
|
-
@param {Object} resolvedModel the value returned from `model`,
|
|
891
|
-
or its resolved value if it was a promise
|
|
892
|
-
@param {Transition} transition
|
|
893
|
-
@return {any | Promise<any>} if the value returned from this hook is
|
|
894
|
-
a promise, the transition will pause until the transition
|
|
895
|
-
resolves. Otherwise, non-promise return values are not
|
|
896
|
-
utilized in any way.
|
|
897
|
-
@since 1.0.0
|
|
898
|
-
@public
|
|
899
|
-
*/
|
|
900
713
|
|
|
714
|
+
beforeModel(_transition) {}
|
|
901
715
|
|
|
902
|
-
afterModel() {}
|
|
716
|
+
afterModel(_resolvedModel, _transition) {}
|
|
903
717
|
/**
|
|
904
718
|
A hook you can implement to optionally redirect to another route.
|
|
905
719
|
Calling `this.transitionTo` from inside of the `redirect` hook will
|
|
@@ -922,7 +736,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
922
736
|
*/
|
|
923
737
|
|
|
924
738
|
|
|
925
|
-
redirect() {}
|
|
739
|
+
redirect(_model, _transition) {}
|
|
926
740
|
/**
|
|
927
741
|
Called when the context is changed by router.js.
|
|
928
742
|
@private
|
|
@@ -1017,11 +831,13 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1017
831
|
|
|
1018
832
|
if (!name) {
|
|
1019
833
|
if (sawParams) {
|
|
834
|
+
// SAFETY: This should be equivalent
|
|
1020
835
|
return Object.assign({}, params);
|
|
1021
836
|
} else {
|
|
1022
837
|
if (transition.resolveIndex < 1) {
|
|
1023
838
|
return;
|
|
1024
|
-
}
|
|
839
|
+
} // SAFETY: This should be correct, but TS is unable to infer this.
|
|
840
|
+
|
|
1025
841
|
|
|
1026
842
|
return transition[STATE_SYMBOL].routeInfos[transition.resolveIndex - 1].context;
|
|
1027
843
|
}
|
|
@@ -1112,30 +928,10 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1112
928
|
set(controller, 'model', context);
|
|
1113
929
|
}
|
|
1114
930
|
}
|
|
1115
|
-
/**
|
|
1116
|
-
Returns the controller of the current route, or a parent (or any ancestor)
|
|
1117
|
-
route in a route hierarchy.
|
|
1118
|
-
The controller instance must already have been created, either through entering the
|
|
1119
|
-
associated route or using `generateController`.
|
|
1120
|
-
```app/routes/post.js
|
|
1121
|
-
import Route from '@ember/routing/route';
|
|
1122
|
-
export default class PostRoute extends Route {
|
|
1123
|
-
setupController(controller, post) {
|
|
1124
|
-
super.setupController(controller, post);
|
|
1125
|
-
this.controllerFor('posts').set('currentPost', post);
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
```
|
|
1129
|
-
@method controllerFor
|
|
1130
|
-
@param {String} name the name of the route or controller
|
|
1131
|
-
@return {Controller}
|
|
1132
|
-
@since 1.0.0
|
|
1133
|
-
@public
|
|
1134
|
-
*/
|
|
1135
931
|
|
|
1136
|
-
|
|
1137
|
-
controllerFor(name, _skipAssert) {
|
|
932
|
+
controllerFor(name, _skipAssert = false) {
|
|
1138
933
|
let owner = getOwner(this);
|
|
934
|
+
assert('Route is unexpectedly missing an owner', owner);
|
|
1139
935
|
let route = owner.lookup(`route:${name}`);
|
|
1140
936
|
|
|
1141
937
|
if (route && route.controllerName) {
|
|
@@ -1169,6 +965,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1169
965
|
|
|
1170
966
|
generateController(name) {
|
|
1171
967
|
let owner = getOwner(this);
|
|
968
|
+
assert('Route is unexpectedly missing an owner', owner);
|
|
1172
969
|
return generateController(owner, name);
|
|
1173
970
|
}
|
|
1174
971
|
/**
|
|
@@ -1210,6 +1007,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1210
1007
|
modelFor(_name) {
|
|
1211
1008
|
let name;
|
|
1212
1009
|
let owner = getOwner(this);
|
|
1010
|
+
assert('Route is unexpectedly missing an owner', owner);
|
|
1213
1011
|
let transition = this._router && this._router._routerMicrolib ? this._router._routerMicrolib.activeTransition : undefined; // Only change the route name when there is an active transition.
|
|
1214
1012
|
// Otherwise, use the passed in route name.
|
|
1215
1013
|
|
|
@@ -1230,7 +1028,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1230
1028
|
}
|
|
1231
1029
|
}
|
|
1232
1030
|
|
|
1233
|
-
return route
|
|
1031
|
+
return route === null || route === void 0 ? void 0 : route.currentModel;
|
|
1234
1032
|
}
|
|
1235
1033
|
/**
|
|
1236
1034
|
`this[RENDER]` is used to render a template into a region of another template
|
|
@@ -1273,39 +1071,6 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1273
1071
|
once(this._router, '_setOutlets');
|
|
1274
1072
|
}
|
|
1275
1073
|
}
|
|
1276
|
-
/**
|
|
1277
|
-
Allows you to produce custom metadata for the route.
|
|
1278
|
-
The return value of this method will be attached to
|
|
1279
|
-
its corresponding RouteInfoWithAttributes object.
|
|
1280
|
-
Example
|
|
1281
|
-
```app/routes/posts/index.js
|
|
1282
|
-
import Route from '@ember/routing/route';
|
|
1283
|
-
export default class PostsIndexRoute extends Route {
|
|
1284
|
-
buildRouteInfoMetadata() {
|
|
1285
|
-
return { title: 'Posts Page' }
|
|
1286
|
-
}
|
|
1287
|
-
}
|
|
1288
|
-
```
|
|
1289
|
-
```app/routes/application.js
|
|
1290
|
-
import Route from '@ember/routing/route';
|
|
1291
|
-
import { service } from '@ember/service';
|
|
1292
|
-
export default class ApplicationRoute extends Route {
|
|
1293
|
-
@service router
|
|
1294
|
-
constructor() {
|
|
1295
|
-
super(...arguments);
|
|
1296
|
-
this.router.on('routeDidChange', transition => {
|
|
1297
|
-
document.title = transition.to.metadata.title;
|
|
1298
|
-
// would update document's title to "Posts Page"
|
|
1299
|
-
});
|
|
1300
|
-
}
|
|
1301
|
-
}
|
|
1302
|
-
```
|
|
1303
|
-
@method buildRouteInfoMetadata
|
|
1304
|
-
@return any
|
|
1305
|
-
@since 3.10.0
|
|
1306
|
-
@public
|
|
1307
|
-
*/
|
|
1308
|
-
|
|
1309
1074
|
|
|
1310
1075
|
buildRouteInfoMetadata() {}
|
|
1311
1076
|
|
|
@@ -1331,7 +1096,8 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1331
1096
|
|
|
1332
1097
|
|
|
1333
1098
|
get store() {
|
|
1334
|
-
|
|
1099
|
+
const owner = getOwner(this);
|
|
1100
|
+
assert('Route is unexpectedly missing an owner', owner);
|
|
1335
1101
|
let routeName = this.routeName;
|
|
1336
1102
|
return {
|
|
1337
1103
|
find(name, value) {
|
|
@@ -1363,6 +1129,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1363
1129
|
let combinedQueryParameterConfiguration;
|
|
1364
1130
|
let controllerName = this.controllerName || this.routeName;
|
|
1365
1131
|
let owner = getOwner(this);
|
|
1132
|
+
assert('Route is unexpectedly missing an owner', owner);
|
|
1366
1133
|
let controller = owner.lookup(`controller:${controllerName}`);
|
|
1367
1134
|
let queryParameterConfiguraton = get(this, 'queryParams');
|
|
1368
1135
|
let hasRouterDefinedQueryParams = Object.keys(queryParameterConfiguraton).length > 0;
|
|
@@ -1372,7 +1139,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1372
1139
|
// this route find its query params and normalize their object shape them
|
|
1373
1140
|
// merge in the query params for the route. As a mergedProperty,
|
|
1374
1141
|
// Route#queryParams is always at least `{}`
|
|
1375
|
-
let controllerDefinedQueryParameterConfiguration = get(controller, 'queryParams') ||
|
|
1142
|
+
let controllerDefinedQueryParameterConfiguration = get(controller, 'queryParams') || [];
|
|
1376
1143
|
let normalizedControllerQueryParameterConfiguration = normalizeControllerQueryParams(controllerDefinedQueryParameterConfiguration);
|
|
1377
1144
|
combinedQueryParameterConfiguration = mergeEachQueryParams(normalizedControllerQueryParameterConfiguration, queryParameterConfiguraton);
|
|
1378
1145
|
} else if (hasRouterDefinedQueryParams) {
|
|
@@ -1444,6 +1211,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1444
1211
|
*/
|
|
1445
1212
|
inactive: (prop, value) => {
|
|
1446
1213
|
let qp = map[prop];
|
|
1214
|
+
assert('expected inactive callback to only be called for registered qps', qp);
|
|
1447
1215
|
|
|
1448
1216
|
this._qpChanged(prop, value, qp);
|
|
1449
1217
|
},
|
|
@@ -1455,6 +1223,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1455
1223
|
*/
|
|
1456
1224
|
active: (prop, value) => {
|
|
1457
1225
|
let qp = map[prop];
|
|
1226
|
+
assert('expected active callback to only be called for registered qps', qp);
|
|
1458
1227
|
|
|
1459
1228
|
this._qpChanged(prop, value, qp);
|
|
1460
1229
|
|
|
@@ -1467,6 +1236,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1467
1236
|
*/
|
|
1468
1237
|
allowOverrides: (prop, value) => {
|
|
1469
1238
|
let qp = map[prop];
|
|
1239
|
+
assert('expected allowOverrides callback to only be called for registered qps', qp);
|
|
1470
1240
|
|
|
1471
1241
|
this._qpChanged(prop, value, qp);
|
|
1472
1242
|
|
|
@@ -1497,7 +1267,9 @@ function routeInfoFor(route, routeInfos, offset = 0) {
|
|
|
1497
1267
|
let current;
|
|
1498
1268
|
|
|
1499
1269
|
for (let i = 0; i < routeInfos.length; i++) {
|
|
1500
|
-
|
|
1270
|
+
let routeInfo = routeInfos[i];
|
|
1271
|
+
assert('has current routeInfo', routeInfo);
|
|
1272
|
+
current = routeInfo.route;
|
|
1501
1273
|
|
|
1502
1274
|
if (current === route) {
|
|
1503
1275
|
return routeInfos[i + offset];
|
|
@@ -1524,6 +1296,7 @@ function buildRenderOptions(route, nameOrOptions, options) {
|
|
|
1524
1296
|
|
|
1525
1297
|
assert('You passed undefined as the outlet name.', isDefaultRender || !(options && 'outlet' in options && options.outlet === undefined));
|
|
1526
1298
|
let owner = getOwner(route);
|
|
1299
|
+
assert('Route is unexpectedly missing an owner', owner);
|
|
1527
1300
|
let name, templateName, into, outlet, model;
|
|
1528
1301
|
let controller = undefined;
|
|
1529
1302
|
|
|
@@ -1618,9 +1391,10 @@ export function getFullQueryParams(router, state) {
|
|
|
1618
1391
|
function getQueryParamsFor(route, state) {
|
|
1619
1392
|
state.queryParamsFor = state.queryParamsFor || {};
|
|
1620
1393
|
let name = route.fullRouteName;
|
|
1394
|
+
let existing = state.queryParamsFor[name];
|
|
1621
1395
|
|
|
1622
|
-
if (
|
|
1623
|
-
return
|
|
1396
|
+
if (existing) {
|
|
1397
|
+
return existing;
|
|
1624
1398
|
}
|
|
1625
1399
|
|
|
1626
1400
|
let fullQueryParams = getFullQueryParams(route._router, state);
|
|
@@ -1629,18 +1403,19 @@ function getQueryParamsFor(route, state) {
|
|
|
1629
1403
|
|
|
1630
1404
|
let qps = get(route, '_qp').qps;
|
|
1631
1405
|
|
|
1632
|
-
for (let
|
|
1406
|
+
for (let qp of qps) {
|
|
1633
1407
|
// Put deserialized qp on params hash.
|
|
1634
|
-
let qp = qps[i];
|
|
1635
1408
|
let qpValueWasPassedIn = (qp.prop in fullQueryParams);
|
|
1636
1409
|
params[qp.prop] = qpValueWasPassedIn ? fullQueryParams[qp.prop] : copyDefaultValue(qp.defaultValue);
|
|
1637
1410
|
}
|
|
1638
1411
|
|
|
1639
1412
|
return params;
|
|
1640
|
-
}
|
|
1413
|
+
} // FIXME: This should probably actually return a `NativeArray` if the passed in value is an Array.
|
|
1414
|
+
|
|
1641
1415
|
|
|
1642
1416
|
function copyDefaultValue(value) {
|
|
1643
1417
|
if (Array.isArray(value)) {
|
|
1418
|
+
// SAFETY: We lost the type data about the array if we don't cast.
|
|
1644
1419
|
return emberA(value.slice());
|
|
1645
1420
|
}
|
|
1646
1421
|
|
|
@@ -1720,54 +1495,12 @@ function getEngineRouteName(engine, routeName) {
|
|
|
1720
1495
|
|
|
1721
1496
|
return routeName;
|
|
1722
1497
|
}
|
|
1723
|
-
/**
|
|
1724
|
-
A hook you can implement to convert the route's model into parameters
|
|
1725
|
-
for the URL.
|
|
1726
|
-
|
|
1727
|
-
```app/router.js
|
|
1728
|
-
// ...
|
|
1729
|
-
|
|
1730
|
-
Router.map(function() {
|
|
1731
|
-
this.route('post', { path: '/posts/:post_id' });
|
|
1732
|
-
});
|
|
1733
|
-
|
|
1734
|
-
```
|
|
1735
|
-
|
|
1736
|
-
```app/routes/post.js
|
|
1737
|
-
import Route from '@ember/routing/route';
|
|
1738
|
-
|
|
1739
|
-
export default class PostRoute extends Route {
|
|
1740
|
-
model({ post_id }) {
|
|
1741
|
-
// the server returns `{ id: 12 }`
|
|
1742
|
-
return fetch(`/posts/${post_id}`;
|
|
1743
|
-
}
|
|
1744
|
-
|
|
1745
|
-
serialize(model) {
|
|
1746
|
-
// this will make the URL `/posts/12`
|
|
1747
|
-
return { post_id: model.id };
|
|
1748
|
-
}
|
|
1749
|
-
}
|
|
1750
|
-
```
|
|
1751
|
-
|
|
1752
|
-
The default `serialize` method will insert the model's `id` into the
|
|
1753
|
-
route's dynamic segment (in this case, `:post_id`) if the segment contains '_id'.
|
|
1754
|
-
If the route has multiple dynamic segments or does not contain '_id', `serialize`
|
|
1755
|
-
will return `getProperties(model, params)`
|
|
1756
1498
|
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
@param {Array} params an Array of parameter names for the current
|
|
1763
|
-
route (in the example, `['post_id']`.
|
|
1764
|
-
@return {Object} the serialized parameters
|
|
1765
|
-
@since 1.0.0
|
|
1766
|
-
@public
|
|
1767
|
-
*/
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
Route.prototype.serialize = defaultSerialize; // Set these here so they can be overridden with extend
|
|
1499
|
+
const defaultSerialize = Route.prototype.serialize;
|
|
1500
|
+
export { defaultSerialize };
|
|
1501
|
+
export function hasDefaultSerialize(route) {
|
|
1502
|
+
return route.serialize === defaultSerialize;
|
|
1503
|
+
} // Set these here so they can be overridden with extend
|
|
1771
1504
|
|
|
1772
1505
|
Route.reopen({
|
|
1773
1506
|
mergedProperties: ['queryParams'],
|
|
@@ -1830,8 +1563,8 @@ Route.reopen({
|
|
|
1830
1563
|
let qpMap = get(this, '_qp').map;
|
|
1831
1564
|
let totalChanged = Object.keys(changed).concat(Object.keys(removed));
|
|
1832
1565
|
|
|
1833
|
-
for (let
|
|
1834
|
-
let qp = qpMap[
|
|
1566
|
+
for (let change of totalChanged) {
|
|
1567
|
+
let qp = qpMap[change];
|
|
1835
1568
|
|
|
1836
1569
|
if (qp) {
|
|
1837
1570
|
let options = this._optionsForQueryParam(qp);
|
|
@@ -1868,8 +1601,7 @@ Route.reopen({
|
|
|
1868
1601
|
let replaceUrl;
|
|
1869
1602
|
stashParamNames(router, routeInfos);
|
|
1870
1603
|
|
|
1871
|
-
for (let
|
|
1872
|
-
let qp = qpMeta.qps[i];
|
|
1604
|
+
for (let qp of qpMeta.qps) {
|
|
1873
1605
|
let route = qp.route;
|
|
1874
1606
|
let controller = route.controller;
|
|
1875
1607
|
let presentKey = qp.urlKey in params && qp.urlKey; // Do a reverse lookup to see if the changed query
|