1 | declare module '@ember/routing/router-service' {
|
2 | import Evented from '@ember/object/evented';
|
3 | import Service from '@ember/service';
|
4 | import type { ModelFor, Transition } from 'router_js';
|
5 | import type Route from '@ember/routing/route';
|
6 | import EmberRouter from '@ember/routing/router';
|
7 | import type { RouteInfo, RouteInfoWithAttributes } from '@ember/routing/lib/route-info';
|
8 | import type { RouteArgs, RouteOptions } from '@ember/routing/lib/utils';
|
9 | export const ROUTER: unique symbol;
|
10 | /**
|
11 | The Router service is the public API that provides access to the router.
|
12 |
|
13 | The immediate benefit of the Router service is that you can inject it into components,
|
14 | giving them a friendly way to initiate transitions and ask questions about the current
|
15 | global router state.
|
16 |
|
17 | In this example, the Router service is injected into a component to initiate a transition
|
18 | to a dedicated route:
|
19 |
|
20 | ```app/components/example.js
|
21 | import Component from '@glimmer/component';
|
22 | import { action } from '@ember/object';
|
23 | import { service } from '@ember/service';
|
24 |
|
25 | export default class ExampleComponent extends Component {
|
26 | @service router;
|
27 |
|
28 | @action
|
29 | next() {
|
30 | this.router.transitionTo('other.route');
|
31 | }
|
32 | }
|
33 | ```
|
34 |
|
35 | Like any service, it can also be injected into helpers, routes, etc.
|
36 |
|
37 | @public
|
38 | @extends Service
|
39 | @class RouterService
|
40 | */
|
41 | interface RouterService extends Evented {
|
42 | on(
|
43 | eventName: 'routeWillChange' | 'routeDidChange',
|
44 | callback: (transition: Transition) => void
|
45 | ): this;
|
46 | }
|
47 | const RouterService_base: Readonly<typeof Service> &
|
48 | (new (owner?: import('@ember/-internals/owner').default | undefined) => Service) &
|
49 | import('@ember/object/mixin').default;
|
50 | class RouterService extends RouterService_base {
|
51 | [ROUTER]?: EmberRouter;
|
52 | get _router(): EmberRouter;
|
53 | willDestroy(): void;
|
54 | /**
|
55 | Transition the application into another route. The route may
|
56 | be either a single route or route path:
|
57 |
|
58 | Calling `transitionTo` from the Router service will cause default query parameter values to be included in the URL.
|
59 | This behavior is different from calling `transitionTo` on a route or `transitionToRoute` on a controller.
|
60 | See the [Router Service RFC](https://github.com/emberjs/rfcs/blob/master/text/0095-router-service.md#query-parameter-semantics) for more info.
|
61 |
|
62 | In the following example we use the Router service to navigate to a route with a
|
63 | specific model from a Component in the first action, and in the second we trigger
|
64 | a query-params only transition.
|
65 |
|
66 | ```app/components/example.js
|
67 | import Component from '@glimmer/component';
|
68 | import { action } from '@ember/object';
|
69 | import { service } from '@ember/service';
|
70 |
|
71 | export default class extends Component {
|
72 | @service router;
|
73 |
|
74 | @action
|
75 | goToComments(post) {
|
76 | this.router.transitionTo('comments', post);
|
77 | }
|
78 |
|
79 | @action
|
80 | fetchMoreComments(latestComment) {
|
81 | this.router.transitionTo({
|
82 | queryParams: { commentsAfter: latestComment }
|
83 | });
|
84 | }
|
85 | }
|
86 | ```
|
87 |
|
88 | @method transitionTo
|
89 | @param {String} [routeNameOrUrl] the name of the route or a URL
|
90 | @param {...Object} [models] the model(s) or identifier(s) to be used while
|
91 | transitioning to the route.
|
92 | @param {Object} [options] optional hash with a queryParams property
|
93 | containing a mapping of query parameters. May be supplied as the only
|
94 | parameter to trigger a query-parameter-only transition.
|
95 | @return {Transition} the transition object associated with this
|
96 | attempted transition
|
97 | @public
|
98 | */
|
99 | transitionTo(...args: RouteArgs): Transition;
|
100 | /**
|
101 | Similar to `transitionTo`, but instead of adding the destination to the browser's URL history,
|
102 | it replaces the entry for the current route.
|
103 | When the user clicks the "back" button in the browser, there will be fewer steps.
|
104 | This is most commonly used to manage redirects in a way that does not cause confusing additions
|
105 | to the user's browsing history.
|
106 |
|
107 | Calling `replaceWith` from the Router service will cause default query parameter values to be included in the URL.
|
108 | This behavior is different from calling `replaceWith` on a route.
|
109 | See the [Router Service RFC](https://github.com/emberjs/rfcs/blob/master/text/0095-router-service.md#query-parameter-semantics) for more info.
|
110 |
|
111 | Usage example:
|
112 |
|
113 | ```app/routes/application.js
|
114 | import Route from '@ember/routing/route';
|
115 | import { service } from '@ember/service';
|
116 |
|
117 | export default class extends Route {
|
118 | @service router;
|
119 | beforeModel() {
|
120 | if (!authorized()){
|
121 | this.router.replaceWith('unauthorized');
|
122 | }
|
123 | }
|
124 | });
|
125 | ```
|
126 |
|
127 | @method replaceWith
|
128 | @param {String} routeNameOrUrl the name of the route or a URL of the desired destination
|
129 | @param {...Object} models the model(s) or identifier(s) to be used while
|
130 | transitioning to the route i.e. an object of params to pass to the destination route
|
131 | @param {Object} [options] optional hash with a queryParams property
|
132 | containing a mapping of query parameters
|
133 | @return {Transition} the transition object associated with this
|
134 | attempted transition
|
135 | @public
|
136 | */
|
137 | replaceWith(...args: RouteArgs): Transition;
|
138 | /**
|
139 | Generate a URL based on the supplied route name and optionally a model. The
|
140 | URL is returned as a string that can be used for any purpose.
|
141 |
|
142 | In this example, the URL for the `author.books` route for a given author
|
143 | is copied to the clipboard.
|
144 |
|
145 | ```app/templates/application.hbs
|
146 | <CopyLink @author={{hash id="tomster" name="Tomster"}} />
|
147 | ```
|
148 |
|
149 | ```app/components/copy-link.js
|
150 | import Component from '@glimmer/component';
|
151 | import { service } from '@ember/service';
|
152 | import { action } from '@ember/object';
|
153 |
|
154 | export default class CopyLinkComponent extends Component {
|
155 | @service router;
|
156 | @service clipboard;
|
157 |
|
158 | @action
|
159 | copyBooksURL() {
|
160 | if (this.author) {
|
161 | const url = this.router.urlFor('author.books', this.args.author);
|
162 | this.clipboard.set(url);
|
163 | // Clipboard now has /author/tomster/books
|
164 | }
|
165 | }
|
166 | }
|
167 | ```
|
168 |
|
169 | Just like with `transitionTo` and `replaceWith`, `urlFor` can also handle
|
170 | query parameters.
|
171 |
|
172 | ```app/templates/application.hbs
|
173 | <CopyLink @author={{hash id="tomster" name="Tomster"}} />
|
174 | ```
|
175 |
|
176 | ```app/components/copy-link.js
|
177 | import Component from '@glimmer/component';
|
178 | import { service } from '@ember/service';
|
179 | import { action } from '@ember/object';
|
180 |
|
181 | export default class CopyLinkComponent extends Component {
|
182 | @service router;
|
183 | @service clipboard;
|
184 |
|
185 | @action
|
186 | copyOnlyEmberBooksURL() {
|
187 | if (this.author) {
|
188 | const url = this.router.urlFor('author.books', this.author, {
|
189 | queryParams: { filter: 'emberjs' }
|
190 | });
|
191 | this.clipboard.set(url);
|
192 | // Clipboard now has /author/tomster/books?filter=emberjs
|
193 | }
|
194 | }
|
195 | }
|
196 | ```
|
197 |
|
198 | @method urlFor
|
199 | @param {String} routeName the name of the route
|
200 | @param {...Object} models the model(s) for the route.
|
201 | @param {Object} [options] optional hash with a queryParams property
|
202 | containing a mapping of query parameters
|
203 | @return {String} the string representing the generated URL
|
204 | @public
|
205 | */
|
206 | urlFor<R extends Route>(
|
207 | routeName: string,
|
208 | ...args: ModelFor<R>[] | [...ModelFor<R>[], RouteOptions]
|
209 | ): string;
|
210 | /**
|
211 | Returns `true` if `routeName/models/queryParams` is the active route, where `models` and `queryParams` are optional.
|
212 | See [model](api/ember/release/classes/Route/methods/model?anchor=model) and
|
213 | [queryParams](/api/ember/3.7/classes/Route/properties/queryParams?anchor=queryParams) for more information about these arguments.
|
214 |
|
215 | In the following example, `isActive` will return `true` if the current route is `/posts`.
|
216 |
|
217 | ```app/components/posts.js
|
218 | import Component from '@glimmer/component';
|
219 | import { service } from '@ember/service';
|
220 |
|
221 | export default class extends Component {
|
222 | @service router;
|
223 |
|
224 | displayComments() {
|
225 | return this.router.isActive('posts');
|
226 | }
|
227 | });
|
228 | ```
|
229 |
|
230 | The next example includes a dynamic segment, and will return `true` if the current route is `/posts/1`,
|
231 | assuming the post has an id of 1:
|
232 |
|
233 | ```app/components/posts.js
|
234 | import Component from '@glimmer/component';
|
235 | import { service } from '@ember/service';
|
236 |
|
237 | export default class extends Component {
|
238 | @service router;
|
239 |
|
240 | displayComments(post) {
|
241 | return this.router.isActive('posts', post.id);
|
242 | }
|
243 | });
|
244 | ```
|
245 |
|
246 | Where `post.id` is the id of a specific post, which is represented in the route as /posts/[post.id].
|
247 | If `post.id` is equal to 1, then isActive will return true if the current route is /posts/1, and false if the route is anything else.
|
248 |
|
249 | @method isActive
|
250 | @param {String} routeName the name of the route
|
251 | @param {...Object} models the model(s) or identifier(s) to be used when determining the active route.
|
252 | @param {Object} [options] optional hash with a queryParams property
|
253 | containing a mapping of query parameters
|
254 | @return {boolean} true if the provided routeName/models/queryParams are active
|
255 | @public
|
256 | */
|
257 | isActive(...args: RouteArgs): boolean;
|
258 | /**
|
259 | Takes a string URL and returns a `RouteInfo` for the leafmost route represented
|
260 | by the URL. Returns `null` if the URL is not recognized. This method expects to
|
261 | receive the actual URL as seen by the browser including the app's `rootURL`.
|
262 |
|
263 | See [RouteInfo](/ember/release/classes/RouteInfo) for more info.
|
264 |
|
265 | In the following example `recognize` is used to verify if a path belongs to our
|
266 | application before transitioning to it.
|
267 |
|
268 | ```
|
269 | import Component from '@ember/component';
|
270 | import { service } from '@ember/service';
|
271 |
|
272 | export default class extends Component {
|
273 | @service router;
|
274 | path = '/';
|
275 |
|
276 | click() {
|
277 | if (this.router.recognize(this.path)) {
|
278 | this.router.transitionTo(this.path);
|
279 | }
|
280 | }
|
281 | }
|
282 | ```
|
283 |
|
284 | @method recognize
|
285 | @param {String} url
|
286 | @return {RouteInfo | null}
|
287 | @public
|
288 | */
|
289 | recognize(url: string): RouteInfo | null;
|
290 | /**
|
291 | Takes a string URL and returns a promise that resolves to a
|
292 | `RouteInfoWithAttributes` for the leafmost route represented by the URL.
|
293 | The promise rejects if the URL is not recognized or an unhandled exception
|
294 | is encountered. This method expects to receive the actual URL as seen by
|
295 | the browser including the app's `rootURL`.
|
296 |
|
297 | @method recognizeAndLoad
|
298 | @param {String} url
|
299 | @return {RouteInfo}
|
300 | @public
|
301 | */
|
302 | recognizeAndLoad(url: string): Promise<RouteInfoWithAttributes>;
|
303 | /**
|
304 | You can register a listener for events emitted by this service with `.on()`:
|
305 |
|
306 | ```app/routes/contact-form.js
|
307 | import Route from '@ember/routing';
|
308 | import { service } from '@ember/service';
|
309 |
|
310 | export default class extends Route {
|
311 | @service router;
|
312 |
|
313 | activate() {
|
314 | this.router.on('routeWillChange', (transition) => {
|
315 | if (!transition.to.find(route => route.name === this.routeName)) {
|
316 | alert("Please save or cancel your changes.");
|
317 | transition.abort();
|
318 | }
|
319 | })
|
320 | }
|
321 | }
|
322 | ```
|
323 |
|
324 | @method on
|
325 | @param {String} eventName
|
326 | @param {Function} callback
|
327 | @public
|
328 | */
|
329 | /**
|
330 | You can unregister a listener for events emitted by this service with `.off()`:
|
331 |
|
332 | ```app/routes/contact-form.js
|
333 | import Route from '@ember/routing';
|
334 | import { service } from '@ember/service';
|
335 |
|
336 | export default class ContactFormRoute extends Route {
|
337 | @service router;
|
338 |
|
339 | callback = (transition) => {
|
340 | if (!transition.to.find(route => route.name === this.routeName)) {
|
341 | alert('Please save or cancel your changes.');
|
342 | transition.abort();
|
343 | }
|
344 | };
|
345 |
|
346 | activate() {
|
347 | this.router.on('routeWillChange', this.callback);
|
348 | }
|
349 |
|
350 | deactivate() {
|
351 | this.router.off('routeWillChange', this.callback);
|
352 | }
|
353 | }
|
354 | ```
|
355 |
|
356 | @method off
|
357 | @param {String} eventName
|
358 | @param {Function} callback
|
359 | @public
|
360 | */
|
361 | /**
|
362 | The `routeWillChange` event is fired at the beginning of any
|
363 | attempted transition with a `Transition` object as the sole
|
364 | argument. This action can be used for aborting, redirecting,
|
365 | or decorating the transition from the currently active routes.
|
366 |
|
367 | A good example is preventing navigation when a form is
|
368 | half-filled out:
|
369 |
|
370 | ```app/routes/contact-form.js
|
371 | import Route from '@ember/routing';
|
372 | import { service } from '@ember/service';
|
373 |
|
374 | export default class extends Route {
|
375 | @service router;
|
376 |
|
377 | activate() {
|
378 | this.router.on('routeWillChange', (transition) => {
|
379 | if (!transition.to.find(route => route.name === this.routeName)) {
|
380 | alert("Please save or cancel your changes.");
|
381 | transition.abort();
|
382 | }
|
383 | })
|
384 | }
|
385 | }
|
386 | ```
|
387 |
|
388 | The `routeWillChange` event fires whenever a new route is chosen as the desired target of a transition. This includes `transitionTo`, `replaceWith`, all redirection for any reason including error handling, and abort. Aborting implies changing the desired target back to where you already were. Once a transition has completed, `routeDidChange` fires.
|
389 |
|
390 | @event routeWillChange
|
391 | @param {Transition} transition
|
392 | @public
|
393 | */
|
394 | /**
|
395 | The `routeDidChange` event only fires once a transition has settled.
|
396 | This includes aborts and error substates. Like the `routeWillChange` event
|
397 | it receives a Transition as the sole argument.
|
398 |
|
399 | A good example is sending some analytics when the route has transitioned:
|
400 |
|
401 | ```app/routes/contact-form.js
|
402 | import Route from '@ember/routing';
|
403 | import { service } from '@ember/service';
|
404 |
|
405 | export default class extends Route {
|
406 | @service router;
|
407 |
|
408 | activate() {
|
409 | this.router.on('routeDidChange', (transition) => {
|
410 | ga.send('pageView', {
|
411 | current: transition.to.name,
|
412 | from: transition.from.name
|
413 | });
|
414 | })
|
415 | }
|
416 | }
|
417 | ```
|
418 |
|
419 | `routeDidChange` will be called after any `Route`'s
|
420 | [didTransition](/ember/release/classes/Route/events/didTransition?anchor=didTransition)
|
421 | action has been fired.
|
422 | The updates of properties
|
423 | [currentURL](/ember/release/classes/RouterService/properties/currentURL?anchor=currentURL),
|
424 | [currentRouteName](/ember/release/classes/RouterService/properties/currentURL?anchor=currentRouteName)
|
425 | and
|
426 | [currentRoute](/ember/release/classes/RouterService/properties/currentURL?anchor=currentRoute)
|
427 | are completed at the time `routeDidChange` is called.
|
428 |
|
429 | @event routeDidChange
|
430 | @param {Transition} transition
|
431 | @public
|
432 | */
|
433 | /**
|
434 | * Refreshes all currently active routes, doing a full transition.
|
435 | * If a route name is provided and refers to a currently active route,
|
436 | * it will refresh only that route and its descendents.
|
437 | * Returns a promise that will be resolved once the refresh is complete.
|
438 | * All resetController, beforeModel, model, afterModel, redirect, and setupController
|
439 | * hooks will be called again. You will get new data from the model hook.
|
440 | *
|
441 | * @method refresh
|
442 | * @param {String} [routeName] the route to refresh (along with all child routes)
|
443 | * @return Transition
|
444 | * @public
|
445 | */
|
446 | refresh(pivotRouteName?: string): Transition;
|
447 | /**
|
448 | Name of the current route.
|
449 |
|
450 | This property represents the logical name of the route,
|
451 | which is dot separated.
|
452 | For the following router:
|
453 |
|
454 | ```app/router.js
|
455 | Router.map(function() {
|
456 | this.route('about');
|
457 | this.route('blog', function () {
|
458 | this.route('post', { path: ':post_id' });
|
459 | });
|
460 | });
|
461 | ```
|
462 |
|
463 | It will return:
|
464 |
|
465 | * `index` when you visit `/`
|
466 | * `about` when you visit `/about`
|
467 | * `blog.index` when you visit `/blog`
|
468 | * `blog.post` when you visit `/blog/some-post-id`
|
469 |
|
470 | @property currentRouteName
|
471 | @type {String | null}
|
472 | @public
|
473 | */
|
474 | readonly currentRouteName: this['_router']['currentRouteName'];
|
475 | /**
|
476 | Current URL for the application.
|
477 |
|
478 | This property represents the URL path for this route.
|
479 | For the following router:
|
480 |
|
481 | ```app/router.js
|
482 | Router.map(function() {
|
483 | this.route('about');
|
484 | this.route('blog', function () {
|
485 | this.route('post', { path: ':post_id' });
|
486 | });
|
487 | });
|
488 | ```
|
489 |
|
490 | It will return:
|
491 |
|
492 | * `/` when you visit `/`
|
493 | * `/about` when you visit `/about`
|
494 | * `/blog` when you visit `/blog`
|
495 | * `/blog/some-post-id` when you visit `/blog/some-post-id`
|
496 |
|
497 | @property currentURL
|
498 | @type String
|
499 | @public
|
500 | */
|
501 | readonly currentURL: this['_router']['currentURL'];
|
502 | /**
|
503 | The `location` property returns what implementation of the `location` API
|
504 | your application is using, which determines what type of URL is being used.
|
505 |
|
506 | See [Location](/ember/release/classes/Location) for more information.
|
507 |
|
508 | To force a particular `location` API implementation to be used in your
|
509 | application you can set a location type on your `config/environment`.
|
510 | For example, to set the `history` type:
|
511 |
|
512 | ```config/environment.js
|
513 | 'use strict';
|
514 |
|
515 | module.exports = function(environment) {
|
516 | let ENV = {
|
517 | modulePrefix: 'router-service',
|
518 | environment,
|
519 | rootURL: '/',
|
520 | locationType: 'history',
|
521 | ...
|
522 | }
|
523 | }
|
524 | ```
|
525 |
|
526 | The following location types are available by default:
|
527 | `hash`, `history`, `none`.
|
528 |
|
529 | See [HashLocation](/ember/release/classes/HashLocation).
|
530 | See [HistoryLocation](/ember/release/classes/HistoryLocation).
|
531 | See [NoneLocation](/ember/release/classes/NoneLocation).
|
532 |
|
533 | @property location
|
534 | @default 'hash'
|
535 | @see {Location}
|
536 | @public
|
537 | */
|
538 | readonly location: this['_router']['location'];
|
539 | /**
|
540 | The `rootURL` property represents the URL of the root of
|
541 | the application, '/' by default.
|
542 | This prefix is assumed on all routes defined on this app.
|
543 |
|
544 | If you change the `rootURL` in your environment configuration
|
545 | like so:
|
546 |
|
547 | ```config/environment.js
|
548 | 'use strict';
|
549 |
|
550 | module.exports = function(environment) {
|
551 | let ENV = {
|
552 | modulePrefix: 'router-service',
|
553 | environment,
|
554 | rootURL: '/my-root',
|
555 | …
|
556 | }
|
557 | ]
|
558 | ```
|
559 |
|
560 | This property will return `/my-root`.
|
561 |
|
562 | @property rootURL
|
563 | @default '/'
|
564 | @public
|
565 | */
|
566 | readonly rootURL: this['_router']['rootURL'];
|
567 | /**
|
568 | The `currentRoute` property contains metadata about the current leaf route.
|
569 | It returns a `RouteInfo` object that has information like the route name,
|
570 | params, query params and more.
|
571 |
|
572 | See [RouteInfo](/ember/release/classes/RouteInfo) for more info.
|
573 |
|
574 | This property is guaranteed to change whenever a route transition
|
575 | happens (even when that transition only changes parameters
|
576 | and doesn't change the active route).
|
577 |
|
578 | Usage example:
|
579 | ```app/components/header.js
|
580 | import Component from '@glimmer/component';
|
581 | import { service } from '@ember/service';
|
582 | import { notEmpty } from '@ember/object/computed';
|
583 |
|
584 | export default class extends Component {
|
585 | @service router;
|
586 |
|
587 | @notEmpty('router.currentRoute.child') isChildRoute;
|
588 | });
|
589 | ```
|
590 |
|
591 | @property currentRoute
|
592 | @type RouteInfo
|
593 | @public
|
594 | */
|
595 | readonly currentRoute: this['_router']['currentRoute'];
|
596 | }
|
597 | export { RouterService as default, type RouteInfo, type RouteInfoWithAttributes };
|
598 | }
|