-
Notifications
You must be signed in to change notification settings - Fork 248
refactor(NgView): Make use of the ViewPort #1069
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -54,7 +54,7 @@ part of angular.routing; | |
@Decorator( | ||
selector: 'ng-view', | ||
module: NgView.module, | ||
visibility: Directive.CHILDREN_VISIBILITY) | ||
children: Directive.TRANSCLUDE_CHILDREN) | ||
class NgView implements DetachAware, RouteProvider { | ||
static final Module _module = new Module() | ||
..bind(RouteProvider, toFactory: (i) => i.get(NgView)); | ||
|
@@ -63,17 +63,16 @@ class NgView implements DetachAware, RouteProvider { | |
final NgRoutingHelper locationService; | ||
final ViewCache viewCache; | ||
final Injector injector; | ||
final Element element; | ||
final Scope scope; | ||
final ViewPort _viewPort; | ||
|
||
RouteHandle _route; | ||
|
||
View _view; | ||
Scope _scope; | ||
Route _viewRoute; | ||
|
||
NgView(this.element, this.viewCache, | ||
Injector injector, Router router, | ||
this.scope) | ||
NgView(this.viewCache, Injector injector, Router router, this.scope, this._viewPort) | ||
: injector = injector, | ||
locationService = injector.get(NgRoutingHelper) | ||
{ | ||
|
@@ -119,24 +118,31 @@ class NgView implements DetachAware, RouteProvider { | |
viewFuture.then((viewFactory) { | ||
_cleanUp(); | ||
_scope = scope.createChild(new PrototypeMap(scope.context)); | ||
_view = viewFactory( | ||
viewInjector.createChild([new Module()..bind(Scope, toValue: _scope)])); | ||
_view.nodes.forEach((elm) => element.append(elm)); | ||
_view = viewFactory(viewInjector.createChild([new Module()..bind(Scope, toValue: _scope)])); | ||
_scope.rootScope.domWrite(() { | ||
_viewPort.insert(_view); | ||
}); | ||
}); | ||
} | ||
|
||
_cleanUp() { | ||
if (_view == null) return; | ||
|
||
_view.nodes.forEach((node) => node.remove()); | ||
_scope.destroy(); | ||
var view = _view; | ||
var childScope = _scope; | ||
_scope.rootScope.domWrite(() { | ||
_viewPort.remove(view); | ||
childScope.destroy(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. destroying scope in domWrite feels odd to me... but I can't say if that will cause issues... just pointing it out... no action required. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. destroying scope in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ping |
||
}); | ||
|
||
_view = null; | ||
_scope = null; | ||
} | ||
|
||
Route get route => _viewRoute; | ||
|
||
String get routeName => _viewRoute.name; | ||
|
||
Map<String, String> get parameters { | ||
var res = <String, String>{}; | ||
var p = _viewRoute; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,57 +28,62 @@ main() { | |
|
||
|
||
it('should switch template', async(() { | ||
Element root = _.compile('<ng-view></ng-view>'); | ||
Element root = _.compile('<div><ng-view></ng-view></div>'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do you wrap these in div? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because ngview need to have a parent for transclude to work as explained in the PR comment. Let me know of anything is unclear. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. actually let me try to put this in a clearer way: Without the wrapping It was perfectly fine before this PR because the nodes were added as children of Now that we use transclusion, the |
||
expect(root.text).toEqual(''); | ||
|
||
router.route('/foo'); | ||
microLeap(); | ||
_.rootScope.flush(); | ||
expect(root.text).toEqual('Foo'); | ||
|
||
router.route('/bar'); | ||
microLeap(); | ||
_.rootScope.flush(); | ||
expect(root.text).toEqual('Bar'); | ||
|
||
router.route('/foo'); | ||
microLeap(); | ||
_.rootScope.flush(); | ||
expect(root.text).toEqual('Foo'); | ||
})); | ||
|
||
it('should expose NgView as RouteProvider', async(() { | ||
_.compile('<ng-view probe="m"></ng-view>'); | ||
_.compile('<div><ng-view probe="m"></ng-view></div>'); | ||
router.route('/foo'); | ||
microLeap(); | ||
_.rootScope.apply(); | ||
_.rootScope.flush(); | ||
|
||
expect(_.rootScope.context['p'].injector.get(RouteProvider) is NgView).toBeTruthy(); | ||
})); | ||
|
||
|
||
it('should switch template when route is already active', async(() { | ||
// Force the routing system to initialize. | ||
_.compile('<ng-view></ng-view>'); | ||
_.compile('<div><ng-view></ng-view></div>'); | ||
|
||
router.route('/foo'); | ||
microLeap(); | ||
Element root = _.compile('<ng-view></ng-view>'); | ||
Element root = _.compile('<div><ng-view></ng-view></div>'); | ||
expect(root.text).toEqual(''); | ||
|
||
_.rootScope.apply(); | ||
microLeap(); | ||
_.rootScope.flush(); | ||
expect(root.text).toEqual('Foo'); | ||
})); | ||
|
||
|
||
it('should clear template when route is deactivated', async(() { | ||
Element root = _.compile('<ng-view></ng-view>'); | ||
Element root = _.compile('<div><ng-view></ng-view></div>'); | ||
expect(root.text).toEqual(''); | ||
|
||
router.route('/foo'); | ||
microLeap(); | ||
_.rootScope.flush(); | ||
expect(root.text).toEqual('Foo'); | ||
|
||
router.route('/baz'); // route without a template | ||
microLeap(); | ||
_.rootScope.flush(); | ||
expect(root.text).toEqual(''); | ||
})); | ||
|
||
|
@@ -111,25 +116,29 @@ main() { | |
}); | ||
|
||
it('should switch nested templates', async(() { | ||
Element root = _.compile('<ng-view></ng-view>'); | ||
Element root = _.compile('<div><ng-view></ng-view></div>'); | ||
expect(root.text).toEqual(''); | ||
|
||
router.route('/library/all'); | ||
microLeap(); | ||
_.rootScope.flush(); | ||
expect(root.text).toEqual('LibraryBooks'); | ||
|
||
router.route('/library/1234'); | ||
microLeap(); | ||
_.rootScope.flush(); | ||
expect(root.text).toEqual('LibraryBook 1234'); | ||
|
||
// nothing should change here | ||
router.route('/library/1234/overview'); | ||
microLeap(); | ||
_.rootScope.flush(); | ||
expect(root.text).toEqual('LibraryBook 1234'); | ||
|
||
// nothing should change here | ||
router.route('/library/1234/read'); | ||
microLeap(); | ||
_.rootScope.flush(); | ||
expect(root.text).toEqual('LibraryRead Book 1234'); | ||
})); | ||
}); | ||
|
@@ -157,11 +166,12 @@ main() { | |
}); | ||
|
||
it('should switch inline templates', async(() { | ||
Element root = _.compile('<ng-view></ng-view>'); | ||
Element root = _.compile('<div><ng-view></ng-view></div>'); | ||
expect(root.text).toEqual(''); | ||
|
||
router.route('/foo'); | ||
microLeap(); | ||
_.rootScope.flush(); | ||
expect(root.text).toEqual('Hello'); | ||
})); | ||
}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change will not work. :-( The issue is that ng-view's are nestable and so they need ChildrenVisibility, otherwise nested routes do not work. The new DirectiveInjector makes it not possible to inject Transcluded controllers. We can change the behavior, but that is the current status. Can we talk about it.
I feel like ngView should be transcluding so that it can properly handle animation, and it is what we do in AngularJS. (https://github.com/angular/angular.js/blob/master/src/ngRoute/directive/ngView.js#L188)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PING, can you address this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also add a test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have this on my todo list, will look at it tomorrow
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
visibility
has been removed because children visibility is the default value (Visibility.CHILDREN
).What kind of tests need to be added ? (We already have tests for nested ng-view.)