From 7329d4714d04e7167bff2dbc4b5f3c4d1de93d35 Mon Sep 17 00:00:00 2001 From: Pavel Jbanov Date: Mon, 26 May 2014 13:25:00 -0400 Subject: [PATCH] feat(router): added vetoable preLeave event BREAKING CHANGE Previously, vetoing was allowed on leave (RouteLeaveEvent) which caused issues because routes had no way to recover from other route vetoing a leave event. Now, similar to preEnter and enter, leave event was split into vetoable preLeave (RoutePreLeaveEvent) and non-vetoable leave (RouteLeaveEvent). views.configure({ 'foo': ngRoute( path: '/foo', preLeave: (RoutePreLeaveEvent e) { e.allowLeave(new Future.value(false)); }) }); --- lib/routing/routing.dart | 12 +++++-- test/angular_spec.dart | 2 ++ test/routing/routing_spec.dart | 60 ++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/lib/routing/routing.dart b/lib/routing/routing.dart index cdba0aa63..70569726b 100644 --- a/lib/routing/routing.dart +++ b/lib/routing/routing.dart @@ -55,6 +55,11 @@ class RouteViewFactory { cfg.preEnter(e); } }, + preLeave: (RoutePreLeaveEvent e) { + if (cfg.preLeave != null) { + cfg.preLeave(e); + } + }, leave: cfg.leave, mount: (Route mountRoute) { if (cfg.mount != null) { @@ -68,10 +73,10 @@ class RouteViewFactory { NgRouteCfg ngRoute({String path, String view, String viewHtml, Map mount, modules(), bool defaultRoute: false, RoutePreEnterEventHandler preEnter, RouteEnterEventHandler enter, - RouteLeaveEventHandler leave}) => + RoutePreLeaveEventHandler preLeave, RouteLeaveEventHandler leave}) => new NgRouteCfg(path: path, view: view, viewHtml: viewHtml, mount: mount, modules: modules, defaultRoute: defaultRoute, preEnter: preEnter, - enter: enter, leave: leave); + preLeave: preLeave, enter: enter, leave: leave); class NgRouteCfg { final String path; @@ -82,10 +87,11 @@ class NgRouteCfg { final bool defaultRoute; final RouteEnterEventHandler enter; final RoutePreEnterEventHandler preEnter; + final RoutePreLeaveEventHandler preLeave; final RouteLeaveEventHandler leave; NgRouteCfg({this.view, this.viewHtml, this.path, this.mount, this.modules, - this.defaultRoute, this.enter, this.preEnter, this.leave}); + this.defaultRoute, this.enter, this.preEnter, this.preLeave, this.leave}); } /** diff --git a/test/angular_spec.dart b/test/angular_spec.dart index def7303c1..cf1da9268 100644 --- a/test/angular_spec.dart +++ b/test/angular_spec.dart @@ -266,6 +266,8 @@ main() { "route.client.RouteLeaveEventHandler", "route.client.RoutePreEnterEvent", "route.client.RoutePreEnterEventHandler", + "route.client.RoutePreLeaveEvent", + "route.client.RoutePreLeaveEventHandler", "route.client.Router", "route.client.RouteStartEvent", "url_matcher.UrlMatch", diff --git a/test/routing/routing_spec.dart b/test/routing/routing_spec.dart index bbc63cd31..e94849708 100644 --- a/test/routing/routing_spec.dart +++ b/test/routing/routing_spec.dart @@ -169,6 +169,66 @@ main() { })); + it('should call preEnter callback and be able to veto', async(() { + int preEnterCount = 0; + initRouter((Router router, RouteViewFactory views) { + views.configure({ + 'foo': ngRoute( + path: '/foo', + preEnter: (RoutePreEnterEvent e) { + preEnterCount++; + e.allowEnter(new Future.value(false)); + }, + view: 'foo.html' + ), + }); + }); + + Element root = _.compile(''); + expect(root.text).toEqual(''); + + router.route('/foo'); + microLeap(); + + expect(preEnterCount).toBe(1); + expect(root.text).toEqual(''); // didn't enter. + })); + + + it('should call preLeave callback and be able to veto', async(() { + int preLeaveCount = 0; + initRouter((Router router, RouteViewFactory views) { + views.configure({ + 'foo': ngRoute( + path: '/foo', + preLeave: (RoutePreLeaveEvent e) { + preLeaveCount++; + e.allowLeave(new Future.value(false)); + }, + view: 'foo.html' + ), + }); + }); + _.injector.get(TemplateCache) + .put('foo.html', new HttpResponse(200, '

Foo

')); + + Element root = _.compile(''); + expect(root.text).toEqual(''); + + router.route('/foo'); + microLeap(); + + expect(preLeaveCount).toBe(0); + expect(root.text).toEqual('Foo'); + + router.route(''); + microLeap(); + + expect(preLeaveCount).toBe(1); + expect(root.text).toEqual('Foo'); // didn't leave. + })); + + it('should call preEnter callback and load modules', async(() { int preEnterCount = 0; int modulesCount = 0;