Skip to content

Commit

Permalink
Merge branch 'MT-PL-SWF-Dev-master'
Browse files Browse the repository at this point in the history
  • Loading branch information
EisenbergEffect committed Nov 30, 2016
2 parents 71438f3 + 5c1c299 commit 2f076a8
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 13 deletions.
58 changes: 46 additions & 12 deletions doc/article/en-US/router-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -691,13 +691,8 @@ Similar to MVC-style master/layout pages, Aurelia allows configuration of multip

## [Internationalizing Titles](aurelia-doc://section/11/version/1.0.0)

If your application targets multiple cultures or languages, you probably want to translate your route titles.
The `Router` class has a `transformTitle` property that can be used for this. It is expected to be assigned a
function that takes the active route's title as parameter and that returns the translated title.

For example, if your app uses `aurelia-i18n`, its routes' titles would typically be set to some translation keys,
and the `AppRouter`'s `transformTitle` would be configure in such a way that the active route's title is translated
using the `I18N`'s `tr` method:
If your application targets multiple cultures or languages, you probably want to translate your route titles. The `Router` class has a `transformTitle` property that can be used for this. It is expected to be assigned a function that takes the active route's title as a parameter and then returns the translated title. For example, if your app uses `aurelia-i18n`, its routes' titles would typically be set to some translation keys
and the `AppRouter`'s `transformTitle` would be configured in such a way that the active route's title is translated using the `I18N`'s `tr` method:

<code-listing heading="src/main${context.language.fileExtension}">
<source-code lang="ES 2015/2016">
Expand Down Expand Up @@ -789,10 +784,49 @@ using the `I18N`'s `tr` method:
</code-listing>

The default value of the`transformTitle` property does the following:
* For child `Router`s, it delegates to its parent's `transformTitle` function.

* For the child `Router`, it delegates to its parent's `transformTitle` function.
* For the `AppRouter`, it returns the title untransformed.

In the previous example, the `AppRouter`'s `transformTitle` is set, so all child `Router`s will
delegate down to it by default.
However, this means that the `transformTitle` can be overriden for specific child `Router`s if
some areas of your app needs custom transformation.
In the previous example, the `AppRouter`'s `transformTitle` is set, so all child `Router`s will delegate down to it by default. However, this means that the `transformTitle` can be overridden for specific child `Router`s if some areas of your app need custom transformation.

## [Configuring a Fallback Route](aurelia-doc://section/12/version/1.0.0)

Whenever navigation is rejected, it is redirected to a previous location. However in certain cases a previous location doesn't exist, e.g. when it happens as the first navigation after the startup of application. To handle this scenario, you can set up a fallback route.

<code-listing heading="app${context.language.fileExtension}">
<source-code lang="ES 2015/2016">
import {RouterConfiguration, Router} from 'aurelia-router';

export class App {
configureRouter(config, router) {
this.router = router;
config.title = 'Aurelia';
config.map([
{ route: ['', 'home'], name: 'home', moduleId: 'home/index' },
{ route: 'users', name: 'users', moduleId: 'users/index', nav: true, caseSensitive: true },
{ route: 'users/:id/detail', name: 'userDetail', moduleId: 'users/detail' }
]);

config.fallbackRoute('users');
}
}
</source-code>
<source-code lang="TypeScript">
import {RouterConfiguration, Router} from 'aurelia-router';

export class App {
configureRouter(config: RouterConfiguration, router: Router): void {
this.router = router;
config.title = 'Aurelia';
config.map([
{ route: ['', 'home'], name: 'home', moduleId: 'home/index' },
{ route: 'users', name: 'users', moduleId: 'users/index', nav: true, caseSensitive: true },
{ route: 'users/:id/detail', name: 'userDetail', moduleId: 'users/detail' }
]);

config.fallbackRoute('users');
}
}
</source-code>
</code-listing>
4 changes: 3 additions & 1 deletion src/app-router.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,9 @@ function restorePreviousLocation(router) {
let previousLocation = router.history.previousLocation;
if (previousLocation) {
router.navigate(router.history.previousLocation, { trigger: false, replace: true });
} else if (router.fallbackRoute) {
router.navigate(router.fallbackRoute, { trigger: true, replace: true });
} else {
logger.error('Router navigation failed, and no previous location could be restored.');
logger.error('Router navigation failed, and no previous location or fallbackRoute could be restored.');
}
}
15 changes: 15 additions & 0 deletions src/router-configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@ export class RouterConfiguration {
return this.addPipelineStep('postRender', step);
}

/**
* Configures a route that will be used if there is no previous location available on navigation cancellation.
*
* @param fragment The URL fragment to use as the navigation destination.
* @chainable
*/
fallbackRoute(fragment: string): RouterConfiguration {
this._fallbackRoute = fragment;
return this;
}

/**
* Maps one or more routes to be registered with the router.
*
Expand Down Expand Up @@ -145,6 +156,10 @@ export class RouterConfiguration {
router.handleUnknownRoutes(this.unknownRouteConfig);
}

if (this._fallbackRoute) {
router.fallbackRoute = this._fallbackRoute;
}

router.options = this.options;

let pipelineSteps = this.pipelineSteps;
Expand Down
14 changes: 14 additions & 0 deletions test/app-router.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,20 @@ describe('app-router', () => {
.then(done);
});

it('navigate to fallback route when route not found and there is no previous location', (done) => {
spyOn(history, 'navigate');

router.history.previousLocation = null;
router.fallbackRoute = "fallback";
router.loadUrl('next')
.then(result => {
expect(result).toBeFalsy();
expect(history.navigate).toHaveBeenCalledWith('#/fallback', { trigger: true, replace: true });
})
.catch(result => expect(true).toBeFalsy('should have succeeded'))
.then(done);
});

it('restores previous location on error', (done) => {
spyOn(history, 'navigate');

Expand Down

0 comments on commit 2f076a8

Please sign in to comment.