UNPKG

22.9 kBTypeScriptView Raw
1declare 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}