Skip to content
This repository has been archived by the owner on Feb 22, 2018. It is now read-only.

feat(Route): allow specifying page title #89

Merged
merged 1 commit into from
May 27, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 30 additions & 15 deletions lib/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ abstract class Route {
*/
bool get dontLeaveOnParamChanges;

/**
* Used to set page title when the route [isActive].
*/
String get pageTitle;

/**
* Returns a stream of [RouteEnterEvent] events. The [RouteEnterEvent] event
* is fired when route has already been made active, but before subroutes
Expand Down Expand Up @@ -121,7 +126,7 @@ abstract class Route {
void addRoute({String name, Pattern path, bool defaultRoute: false,
RouteEnterEventHandler enter, RoutePreEnterEventHandler preEnter,
RoutePreLeaveEventHandler preLeave, RouteLeaveEventHandler leave,
mount, dontLeaveOnParamChanges: false,
mount, dontLeaveOnParamChanges: false, String pageTitle,
List<Pattern> watchQueryParameters});

/**
Expand Down Expand Up @@ -166,6 +171,8 @@ class RouteImpl extends Route {
final UrlMatcher path;
@override
final RouteImpl parent;
@override
final String pageTitle;

/// Child routes map route names to `Route` instances
final _routes = <String, RouteImpl>{};
Expand Down Expand Up @@ -199,7 +206,7 @@ class RouteImpl extends Route {
Stream<RouteEvent> get onEnter => _onEnterController.stream;

RouteImpl._new({this.name, this.path, this.parent,
this.dontLeaveOnParamChanges: false,
this.dontLeaveOnParamChanges: false, this.pageTitle,
watchQueryParameters})
: _onEnterController =
new StreamController<RouteEnterEvent>.broadcast(sync: true),
Expand All @@ -215,7 +222,7 @@ class RouteImpl extends Route {
void addRoute({String name, Pattern path, bool defaultRoute: false,
RouteEnterEventHandler enter, RoutePreEnterEventHandler preEnter,
RoutePreLeaveEventHandler preLeave, RouteLeaveEventHandler leave,
mount, dontLeaveOnParamChanges: false,
mount, dontLeaveOnParamChanges: false, String pageTitle,
List<Pattern> watchQueryParameters}) {
if (name == null) {
throw new ArgumentError('name is required for all routes');
Expand All @@ -230,7 +237,7 @@ class RouteImpl extends Route {
var matcher = path is UrlMatcher ? path : new UrlTemplate(path.toString());

var route = new RouteImpl._new(name: name, path: matcher, parent: this,
dontLeaveOnParamChanges: dontLeaveOnParamChanges,
dontLeaveOnParamChanges: dontLeaveOnParamChanges, pageTitle: pageTitle,
watchQueryParameters: watchQueryParameters);

route..onPreEnter.listen(preEnter)
Expand Down Expand Up @@ -286,12 +293,8 @@ class RouteImpl extends Route {
return tail;
}

String _getTailUrl(String routePath, Map parameters) {
String _getTailUrl(Route routeToGo, Map parameters) {
var tail = '';
var routeToGo = findRoute(routePath);
if (routeToGo == null) {
throw new StateError('Invalid route path: $routePath');
}
for (RouteImpl route = routeToGo; route != this; route = route.parent) {
tail = route.path.reverse(
parameters: _joinParams(parameters == null ?
Expand Down Expand Up @@ -714,14 +717,15 @@ class Router {
Future<bool> go(String routePath, Map parameters, {Route startingFrom,
bool replace: false, Map queryParameters, bool forceReload: false}) {
RouteImpl baseRoute = startingFrom == null ? root : _dehandle(startingFrom);
var newTail = baseRoute._getTailUrl(routePath, parameters) +
var routeToGo = _findRoute(baseRoute, routePath);
var newTail = baseRoute._getTailUrl(routeToGo, parameters) +
_buildQuery(queryParameters);
String newUrl = baseRoute._getHead(newTail);
_logger.finest('go $newUrl');
return route(newTail, startingFrom: baseRoute, forceReload: forceReload)
.then((success) {
if (success) {
_go(newUrl, null, replace);
_go(newUrl, routeToGo.pageTitle, replace);
}
return success;
});
Expand All @@ -732,11 +736,22 @@ class Router {
Map queryParameters}) {
var baseRoute = startingFrom == null ? root : _dehandle(startingFrom);
parameters = parameters == null ? {} : parameters;
var tail = baseRoute._getTailUrl(routePath, parameters);
var routeToGo = _findRoute(baseRoute, routePath);
var tail = baseRoute._getTailUrl(routeToGo, parameters);
return (_useFragment ? '#' : '') + baseRoute._getHead(tail) +
_buildQuery(queryParameters);
}

/// Attempts to find [Route] for the specified [routePath] relative to the
/// [baseRoute]. If nothing is found throws a [StateError].
Route _findRoute(Route baseRoute, String routePath) {
var route = baseRoute.findRoute(routePath);
if (route == null) {
throw new StateError('Invalid route path: $routePath');
}
return route;
}

/// Build an query string from a parameter `Map`
String _buildQuery(Map queryParams) {
if (queryParams == null || queryParams.isEmpty) {
Expand Down Expand Up @@ -856,9 +871,6 @@ class Router {
} else {
_window.location.assign('#$path');
}
if (title != null) {
(_window.document as HtmlDocument).title = title;
}
} else {
if (title == null) {
title = (_window.document as HtmlDocument).title;
Expand All @@ -869,6 +881,9 @@ class Router {
_window.history.pushState(null, title, path);
}
}
if (title != null) {
(_window.document as HtmlDocument).title = title;
}
}

/**
Expand Down
8 changes: 6 additions & 2 deletions lib/route_handle.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ class RouteHandle implements Route {
@override
void addRoute({String name, Pattern path, bool defaultRoute: false,
RouteEnterEventHandler enter, RoutePreEnterEventHandler preEnter,
RoutePreLeaveEventHandler preLeave,RouteLeaveEventHandler leave,
mount, dontLeaveOnParamChanges: false,
RoutePreLeaveEventHandler preLeave, RouteLeaveEventHandler leave,
mount, dontLeaveOnParamChanges: false, String pageTitle,
List<Pattern> watchQueryParameters}) {
throw new UnsupportedError('addRoute is not supported in handle');
}
Expand Down Expand Up @@ -134,6 +134,10 @@ class RouteHandle implements Route {
@override
bool get dontLeaveOnParamChanges => _route.dontLeaveOnParamChanges;

/// See [Route.title]
@override
String get pageTitle => _route.pageTitle;

@override
Map get queryParameters => _route.queryParameters;
}
26 changes: 26 additions & 0 deletions test/client_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1243,6 +1243,32 @@ main() {
});
});

test('should update page title if the title property is set', () {
var mockWindow = new MockWindow();
var router = new Router(useFragment: false, windowImpl: mockWindow);
router.root.addRoute(name: 'foo', path: '/foo', pageTitle: 'Foo');

router.go('foo', {}).then(expectAsync((_) {
var mockHistory = mockWindow.history;
mockWindow.document.getLogs(callsTo('set title')).verify(happenedOnce);
expect(mockHistory.getLogs(callsTo('pushState', anything)).last.args,
[null, 'Foo', '/foo']);
}));
});

test('should not change page title if the title property is not set', () {
var mockWindow = new MockWindow();
mockWindow.document.when(callsTo('get title')).alwaysReturn('page title');
var router = new Router(useFragment: false, windowImpl: mockWindow);
router.root.addRoute(name: 'foo', path: '/foo');

router.go('foo', {}).then(expectAsync((_) {
var mockHistory = mockWindow.history;
expect(mockHistory.getLogs(callsTo('pushState', anything)).last.args,
[null, 'page title', '/foo']);
}));
});

});

group('url', () {
Expand Down