ember-source 4.3.0-alpha.4 → 4.3.0-beta.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 +16 -13
- package/dist/ember-template-compiler.map +1 -1
- package/dist/ember-testing.js +1 -1
- package/dist/ember-testing.map +1 -1
- package/dist/ember.debug.js +669 -1204
- package/dist/ember.debug.map +1 -1
- package/dist/header/license.js +1 -1
- package/dist/packages/@ember/-internals/container/index.js +14 -10
- package/dist/packages/@ember/-internals/glimmer/index.js +60 -45
- 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/services/router.js +153 -191
- package/dist/packages/@ember/-internals/routing/lib/system/route-info.js +2 -2
- package/dist/packages/@ember/-internals/routing/lib/system/route.js +95 -374
- package/dist/packages/@ember/-internals/routing/lib/system/router.js +60 -33
- package/dist/packages/@ember/-internals/routing/lib/utils.js +31 -20
- package/dist/packages/@ember/-internals/runtime/lib/mixins/action_handler.js +32 -32
- package/dist/packages/@ember/-internals/utils/index.js +2 -0
- package/dist/packages/@ember/-internals/views/lib/system/utils.js +1 -0
- package/dist/packages/@ember/canary-features/index.js +2 -2
- package/dist/packages/@ember/controller/index.js +3 -54
- 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/version.js +1 -1
- package/docs/data.json +412 -344
- package/package.json +4 -4
|
@@ -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.
|
|
@@ -118,9 +139,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
118
139
|
namePaths[a] = `${routeInfo.name}.${names[a]}`;
|
|
119
140
|
}
|
|
120
141
|
|
|
121
|
-
for (let
|
|
122
|
-
let qp = qps[i];
|
|
123
|
-
|
|
142
|
+
for (let qp of qps) {
|
|
124
143
|
if (qp.scope === 'model') {
|
|
125
144
|
qp.parts = namePaths;
|
|
126
145
|
}
|
|
@@ -203,9 +222,9 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
203
222
|
let fullName = route.fullRouteName;
|
|
204
223
|
let params = Object.assign({}, state.params[fullName]);
|
|
205
224
|
let queryParams = getQueryParamsFor(route, state);
|
|
206
|
-
return Object.
|
|
225
|
+
return Object.entries(queryParams).reduce((params, [key, value]) => {
|
|
207
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]);
|
|
208
|
-
params[key] =
|
|
227
|
+
params[key] = value;
|
|
209
228
|
return params;
|
|
210
229
|
}, params);
|
|
211
230
|
}
|
|
@@ -322,148 +341,6 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
322
341
|
this.activate(transition);
|
|
323
342
|
this.trigger('activate', transition);
|
|
324
343
|
}
|
|
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
344
|
/**
|
|
468
345
|
This event is triggered when the router enters the route. It is
|
|
469
346
|
not executed when the model for the route changes.
|
|
@@ -774,14 +651,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
774
651
|
setup(context, transition) {
|
|
775
652
|
let controllerName = this.controllerName || this.routeName;
|
|
776
653
|
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
|
-
|
|
654
|
+
let controller = definedController !== null && definedController !== void 0 ? definedController : this.generateController(controllerName); // SAFETY: Since `_qp` is protected we can't infer the type
|
|
785
655
|
|
|
786
656
|
let queryParams = get(this, '_qp'); // Assign the route's controller so that it can more easily be
|
|
787
657
|
// referenced in action handlers. Side effects. Side effects everywhere.
|
|
@@ -803,6 +673,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
803
673
|
let allParams = queryParams.propertyNames;
|
|
804
674
|
allParams.forEach(prop => {
|
|
805
675
|
let aQp = queryParams.map[prop];
|
|
676
|
+
assert('expected aQp', aQp);
|
|
806
677
|
aQp.values = params;
|
|
807
678
|
let cacheKey = calculateCacheKey(aQp.route.fullRouteName, aQp.parts, aQp.values);
|
|
808
679
|
let value = cache.lookup(cacheKey, prop, aQp.undecoratedDefaultValue);
|
|
@@ -839,71 +710,10 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
839
710
|
let cacheKey = calculateCacheKey(qp.route.fullRouteName, qp.parts, qp.values);
|
|
840
711
|
cache.stash(cacheKey, prop, value);
|
|
841
712
|
}
|
|
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
713
|
|
|
714
|
+
beforeModel(_transition) {}
|
|
871
715
|
|
|
872
|
-
|
|
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
|
-
|
|
905
|
-
|
|
906
|
-
afterModel() {}
|
|
716
|
+
afterModel(_resolvedModel, _transition) {}
|
|
907
717
|
/**
|
|
908
718
|
A hook you can implement to optionally redirect to another route.
|
|
909
719
|
Calling `this.transitionTo` from inside of the `redirect` hook will
|
|
@@ -926,7 +736,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
926
736
|
*/
|
|
927
737
|
|
|
928
738
|
|
|
929
|
-
redirect() {}
|
|
739
|
+
redirect(_model, _transition) {}
|
|
930
740
|
/**
|
|
931
741
|
Called when the context is changed by router.js.
|
|
932
742
|
@private
|
|
@@ -1021,11 +831,14 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1021
831
|
|
|
1022
832
|
if (!name) {
|
|
1023
833
|
if (sawParams) {
|
|
834
|
+
// SAFETY: This should be equivalent
|
|
1024
835
|
return Object.assign({}, params);
|
|
1025
836
|
} else {
|
|
1026
837
|
if (transition.resolveIndex < 1) {
|
|
1027
838
|
return;
|
|
1028
|
-
}
|
|
839
|
+
} // SAFETY: These return types should be equivalent but router.js doesn't have enough
|
|
840
|
+
// generics to infer it.
|
|
841
|
+
|
|
1029
842
|
|
|
1030
843
|
return transition[STATE_SYMBOL].routeInfos[transition.resolveIndex - 1].context;
|
|
1031
844
|
}
|
|
@@ -1116,29 +929,8 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1116
929
|
set(controller, 'model', context);
|
|
1117
930
|
}
|
|
1118
931
|
}
|
|
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
932
|
|
|
1141
|
-
controllerFor(name, _skipAssert) {
|
|
933
|
+
controllerFor(name, _skipAssert = false) {
|
|
1142
934
|
let owner = getOwner(this);
|
|
1143
935
|
assert('Route is unexpectedly missing an owner', owner);
|
|
1144
936
|
let route = owner.lookup(`route:${name}`);
|
|
@@ -1237,7 +1029,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1237
1029
|
}
|
|
1238
1030
|
}
|
|
1239
1031
|
|
|
1240
|
-
return route
|
|
1032
|
+
return route === null || route === void 0 ? void 0 : route.currentModel;
|
|
1241
1033
|
}
|
|
1242
1034
|
/**
|
|
1243
1035
|
`this[RENDER]` is used to render a template into a region of another template
|
|
@@ -1280,39 +1072,6 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1280
1072
|
once(this._router, '_setOutlets');
|
|
1281
1073
|
}
|
|
1282
1074
|
}
|
|
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
1075
|
|
|
1317
1076
|
buildRouteInfoMetadata() {}
|
|
1318
1077
|
|
|
@@ -1381,7 +1140,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1381
1140
|
// this route find its query params and normalize their object shape them
|
|
1382
1141
|
// merge in the query params for the route. As a mergedProperty,
|
|
1383
1142
|
// Route#queryParams is always at least `{}`
|
|
1384
|
-
let controllerDefinedQueryParameterConfiguration = get(controller, 'queryParams') ||
|
|
1143
|
+
let controllerDefinedQueryParameterConfiguration = get(controller, 'queryParams') || [];
|
|
1385
1144
|
let normalizedControllerQueryParameterConfiguration = normalizeControllerQueryParams(controllerDefinedQueryParameterConfiguration);
|
|
1386
1145
|
combinedQueryParameterConfiguration = mergeEachQueryParams(normalizedControllerQueryParameterConfiguration, queryParameterConfiguraton);
|
|
1387
1146
|
} else if (hasRouterDefinedQueryParams) {
|
|
@@ -1453,6 +1212,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1453
1212
|
*/
|
|
1454
1213
|
inactive: (prop, value) => {
|
|
1455
1214
|
let qp = map[prop];
|
|
1215
|
+
assert('expected inactive callback to only be called for registered qps', qp);
|
|
1456
1216
|
|
|
1457
1217
|
this._qpChanged(prop, value, qp);
|
|
1458
1218
|
},
|
|
@@ -1464,6 +1224,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1464
1224
|
*/
|
|
1465
1225
|
active: (prop, value) => {
|
|
1466
1226
|
let qp = map[prop];
|
|
1227
|
+
assert('expected active callback to only be called for registered qps', qp);
|
|
1467
1228
|
|
|
1468
1229
|
this._qpChanged(prop, value, qp);
|
|
1469
1230
|
|
|
@@ -1476,6 +1237,7 @@ class Route extends EmberObject.extend(ActionHandler, Evented) {
|
|
|
1476
1237
|
*/
|
|
1477
1238
|
allowOverrides: (prop, value) => {
|
|
1478
1239
|
let qp = map[prop];
|
|
1240
|
+
assert('expected allowOverrides callback to only be called for registered qps', qp);
|
|
1479
1241
|
|
|
1480
1242
|
this._qpChanged(prop, value, qp);
|
|
1481
1243
|
|
|
@@ -1506,7 +1268,9 @@ function routeInfoFor(route, routeInfos, offset = 0) {
|
|
|
1506
1268
|
let current;
|
|
1507
1269
|
|
|
1508
1270
|
for (let i = 0; i < routeInfos.length; i++) {
|
|
1509
|
-
|
|
1271
|
+
let routeInfo = routeInfos[i];
|
|
1272
|
+
assert('has current routeInfo', routeInfo);
|
|
1273
|
+
current = routeInfo.route;
|
|
1510
1274
|
|
|
1511
1275
|
if (current === route) {
|
|
1512
1276
|
return routeInfos[i + offset];
|
|
@@ -1628,9 +1392,10 @@ export function getFullQueryParams(router, state) {
|
|
|
1628
1392
|
function getQueryParamsFor(route, state) {
|
|
1629
1393
|
state.queryParamsFor = state.queryParamsFor || {};
|
|
1630
1394
|
let name = route.fullRouteName;
|
|
1395
|
+
let existing = state.queryParamsFor[name];
|
|
1631
1396
|
|
|
1632
|
-
if (
|
|
1633
|
-
return
|
|
1397
|
+
if (existing) {
|
|
1398
|
+
return existing;
|
|
1634
1399
|
}
|
|
1635
1400
|
|
|
1636
1401
|
let fullQueryParams = getFullQueryParams(route._router, state);
|
|
@@ -1639,9 +1404,8 @@ function getQueryParamsFor(route, state) {
|
|
|
1639
1404
|
|
|
1640
1405
|
let qps = get(route, '_qp').qps;
|
|
1641
1406
|
|
|
1642
|
-
for (let
|
|
1407
|
+
for (let qp of qps) {
|
|
1643
1408
|
// Put deserialized qp on params hash.
|
|
1644
|
-
let qp = qps[i];
|
|
1645
1409
|
let qpValueWasPassedIn = (qp.prop in fullQueryParams);
|
|
1646
1410
|
params[qp.prop] = qpValueWasPassedIn ? fullQueryParams[qp.prop] : copyDefaultValue(qp.defaultValue);
|
|
1647
1411
|
}
|
|
@@ -1732,54 +1496,12 @@ function getEngineRouteName(engine, routeName) {
|
|
|
1732
1496
|
|
|
1733
1497
|
return routeName;
|
|
1734
1498
|
}
|
|
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
|
-
|
|
1746
|
-
```
|
|
1747
|
-
|
|
1748
|
-
```app/routes/post.js
|
|
1749
|
-
import Route from '@ember/routing/route';
|
|
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
1499
|
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
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
|
|
1500
|
+
const defaultSerialize = Route.prototype.serialize;
|
|
1501
|
+
export { defaultSerialize };
|
|
1502
|
+
export function hasDefaultSerialize(route) {
|
|
1503
|
+
return route.serialize === defaultSerialize;
|
|
1504
|
+
} // Set these here so they can be overridden with extend
|
|
1783
1505
|
|
|
1784
1506
|
Route.reopen({
|
|
1785
1507
|
mergedProperties: ['queryParams'],
|
|
@@ -1842,8 +1564,8 @@ Route.reopen({
|
|
|
1842
1564
|
let qpMap = get(this, '_qp').map;
|
|
1843
1565
|
let totalChanged = Object.keys(changed).concat(Object.keys(removed));
|
|
1844
1566
|
|
|
1845
|
-
for (let
|
|
1846
|
-
let qp = qpMap[
|
|
1567
|
+
for (let change of totalChanged) {
|
|
1568
|
+
let qp = qpMap[change];
|
|
1847
1569
|
|
|
1848
1570
|
if (qp) {
|
|
1849
1571
|
let options = this._optionsForQueryParam(qp);
|
|
@@ -1880,8 +1602,7 @@ Route.reopen({
|
|
|
1880
1602
|
let replaceUrl;
|
|
1881
1603
|
stashParamNames(router, routeInfos);
|
|
1882
1604
|
|
|
1883
|
-
for (let
|
|
1884
|
-
let qp = qpMeta.qps[i];
|
|
1605
|
+
for (let qp of qpMeta.qps) {
|
|
1885
1606
|
let route = qp.route;
|
|
1886
1607
|
let controller = route.controller;
|
|
1887
1608
|
let presentKey = qp.urlKey in params && qp.urlKey; // Do a reverse lookup to see if the changed query
|