Skip to content

Commit 923d90b

Browse files
committed
refactor(views): clean up creating views in place and extract view_hydrator
Major changes: - `compiler.compileRoot(el, type)` -> `compiler.compileInHost(type) + viewHydrator.hydrateHostViewInPlace(el, view)` - move all `hydrate`/`dehydrate` methods out of `View` and `ViewContainer` into a standalone class `view_hydrator` as private methods and provide new public methods dedicated to the individual use cases. Note: This PR does not change the current functionality, only moves it into different places. See design discussion in angular#1351, in preparation for imperative views.
1 parent 97fc248 commit 923d90b

35 files changed

+1014
-764
lines changed

modules/angular2/src/core/application.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,13 @@ import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
2929
import {ComponentRef, DynamicComponentLoader} from 'angular2/src/core/compiler/dynamic_component_loader';
3030
import {TestabilityRegistry, Testability} from 'angular2/src/core/testability/testability';
3131
import {ViewFactory, VIEW_POOL_CAPACITY} from 'angular2/src/core/compiler/view_factory';
32+
import {AppViewHydrator} from 'angular2/src/core/compiler/view_hydrator';
3233
import {ProtoViewFactory} from 'angular2/src/core/compiler/proto_view_factory';
3334
import {Renderer} from 'angular2/src/render/api';
3435
import {DirectDomRenderer} from 'angular2/src/render/dom/direct_dom_renderer';
3536
import * as rc from 'angular2/src/render/dom/compiler/compiler';
3637
import * as rvf from 'angular2/src/render/dom/view/view_factory';
38+
import * as rvh from 'angular2/src/render/dom/view/view_hydrator';
3739

3840
import {
3941
appComponentRefToken,
@@ -98,14 +100,16 @@ function _injectorBindings(appComponentType): List<Binding> {
98100
[rvf.VIEW_POOL_CAPACITY, EventManager, ShadowDomStrategy]
99101
),
100102
bind(rvf.VIEW_POOL_CAPACITY).toValue(10000),
103+
rvh.RenderViewHydrator,
101104
ProtoViewFactory,
102105
// TODO(tbosch): We need an explicit factory here, as
103106
// we are getting errors in dart2js with mirrors...
104107
bind(ViewFactory).toFactory(
105-
(capacity) => new ViewFactory(capacity),
106-
[VIEW_POOL_CAPACITY]
108+
(capacity, renderer) => new ViewFactory(capacity, renderer),
109+
[VIEW_POOL_CAPACITY, Renderer]
107110
),
108111
bind(VIEW_POOL_CAPACITY).toValue(10000),
112+
AppViewHydrator,
109113
Compiler,
110114
CompilerCache,
111115
TemplateResolver,

modules/angular2/src/core/compiler/compiler.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,11 @@ export class Compiler {
8181
return DirectiveBinding.createFromType(meta.type, meta.annotation);
8282
}
8383

84-
// Create a rootView as if the compiler encountered <rootcmp></rootcmp>.
84+
// Create a hostView as if the compiler encountered <hostcmp></hostcmp>.
8585
// Used for bootstrapping.
86-
compileRoot(elementOrSelector, componentTypeOrBinding:any):Promise<AppProtoView> {
87-
return this._renderer.createRootProtoView(elementOrSelector, 'root').then( (rootRenderPv) => {
88-
return this._compileNestedProtoViews(null, rootRenderPv, [this._bindDirective(componentTypeOrBinding)], true);
86+
compileInHost(componentTypeOrBinding:any):Promise<AppProtoView> {
87+
return this._renderer.createHostProtoView('host').then( (hostRenderPv) => {
88+
return this._compileNestedProtoViews(null, hostRenderPv, [this._bindDirective(componentTypeOrBinding)], true);
8989
});
9090
}
9191

modules/angular2/src/core/compiler/dynamic_component_loader.js

Lines changed: 20 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@ import {Key, Injector, Injectable, ResolvedBinding} from 'angular2/di'
22
import {Compiler} from './compiler';
33
import {DirectiveMetadataReader} from './directive_metadata_reader';
44
import {Type, BaseException, stringify, isPresent} from 'angular2/src/facade/lang';
5-
import {List} from 'angular2/src/facade/collection';
65
import {Promise} from 'angular2/src/facade/async';
76
import {Component} from 'angular2/src/core/annotations/annotations';
87
import {ViewFactory} from 'angular2/src/core/compiler/view_factory';
9-
import {Renderer} from 'angular2/src/render/api';
10-
import {ElementRef} from './element_injector';
8+
import {AppViewHydrator} from 'angular2/src/core/compiler/view_hydrator';
9+
import {ElementRef, DirectiveBinding} from './element_injector';
1110
import {AppView} from './view';
1211

1312
/**
@@ -43,13 +42,15 @@ export class ComponentRef {
4342
export class DynamicComponentLoader {
4443
_compiler:Compiler;
4544
_viewFactory:ViewFactory;
45+
_viewHydrator:AppViewHydrator;
4646
_directiveMetadataReader:DirectiveMetadataReader;
4747

4848
constructor(compiler:Compiler, directiveMetadataReader:DirectiveMetadataReader,
49-
renderer:Renderer, viewFactory:ViewFactory) {
49+
viewFactory:ViewFactory, viewHydrator:AppViewHydrator) {
5050
this._compiler = compiler;
5151
this._directiveMetadataReader = directiveMetadataReader;
52-
this._viewFactory = viewFactory
52+
this._viewFactory = viewFactory;
53+
this._viewHydrator = viewHydrator;
5354
}
5455

5556
/**
@@ -58,61 +59,44 @@ export class DynamicComponentLoader {
5859
*/
5960
loadIntoExistingLocation(type:Type, location:ElementRef, injector:Injector = null):Promise<ComponentRef> {
6061
this._assertTypeIsComponent(type);
62+
var annotation = this._directiveMetadataReader.read(type).annotation;
63+
var componentBinding = DirectiveBinding.createFromType(type, annotation);
6164

62-
var directiveMetadata = this._directiveMetadataReader.read(type);
63-
64-
var inj = this._componentAppInjector(location, injector, directiveMetadata.resolvedInjectables);
65-
66-
var hostEi = location.elementInjector;
67-
var hostView = location.hostView;
6865
return this._compiler.compile(type).then(componentProtoView => {
69-
var component = hostEi.dynamicallyCreateComponent(type, directiveMetadata.annotation, inj);
70-
var componentView = this._instantiateAndHydrateView(componentProtoView, injector, hostEi, component);
71-
72-
//TODO(vsavkin): do not use component child views as we need to clear the dynamically created views
73-
//same problem exists on the render side
74-
hostView.setDynamicComponentChildView(location.boundElementIndex, componentView);
66+
var componentView = this._viewFactory.getView(componentProtoView);
67+
var hostView = location.hostView;
68+
this._viewHydrator.hydrateDynamicComponentView(
69+
hostView, location.boundElementIndex, componentView, componentBinding, injector);
7570

7671
// TODO(vsavkin): return a component ref that dehydrates the component view and removes it
7772
// from the component child views
78-
return new ComponentRef(location, component, componentView);
73+
// See ViewFactory.returnView
74+
// See AppViewHydrator.dehydrateDynamicComponentView
75+
return new ComponentRef(location, location.elementInjector.getDynamicallyLoadedComponent(), componentView);
7976
});
8077
}
8178

8279
/**
8380
* Loads a component as a child of the View given by the provided ElementRef. The loaded
8481
* component receives injection normally as a hosted view.
85-
*
86-
* TODO(vsavkin, jelbourn): remove protoViewFactory after render layer exists.
8782
*/
8883
loadIntoNewLocation(elementOrSelector:any, type:Type, location:ElementRef,
8984
injector:Injector = null):Promise<ComponentRef> {
9085
this._assertTypeIsComponent(type);
9186

92-
var inj = this._componentAppInjector(location, injector, null);
93-
94-
//TODO(tbosch) this should always be a selector
95-
return this._compiler.compileRoot(elementOrSelector, type).then(pv => {
96-
var hostView = this._instantiateAndHydrateView(pv, inj, null, new Object());
87+
return this._compiler.compileInHost(type).then(hostProtoView => {
88+
var hostView = this._viewFactory.getView(hostProtoView);
89+
this._viewHydrator.hydrateInPlaceHostView(null, elementOrSelector, hostView, injector);
9790

9891
// TODO(vsavkin): return a component ref that dehydrates the host view
92+
// See ViewFactory.returnView
93+
// See AppViewHydrator.dehydrateInPlaceHostView
9994
var newLocation = new ElementRef(hostView.elementInjectors[0]);
10095
var component = hostView.elementInjectors[0].getComponent();
10196
return new ComponentRef(newLocation, component, hostView.componentChildViews[0]);
10297
});
10398
}
10499

105-
_componentAppInjector(location, injector:Injector, resolvedBindings:List<ResolvedBinding>) {
106-
var inj = isPresent(injector) ? injector : location.injector;
107-
return isPresent(resolvedBindings) ? inj.createChildFromResolved(resolvedBindings) : inj;
108-
}
109-
110-
_instantiateAndHydrateView(protoView, injector, hostElementInjector, context) {
111-
var componentView = this._viewFactory.getView(protoView);
112-
componentView.hydrate(injector, hostElementInjector, context, null);
113-
return componentView;
114-
}
115-
116100
/** Asserts that the type being dynamically instantiated is a Component. */
117101
_assertTypeIsComponent(type:Type) {
118102
var annotation = this._directiveMetadataReader.read(type).annotation;

modules/angular2/src/core/compiler/element_injector.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -575,9 +575,9 @@ export class ElementInjector extends TreeNode {
575575
if (isPresent(p._keyId9)) this._getDirectiveByKeyId(p._keyId9);
576576
}
577577

578-
dynamicallyCreateComponent(componentType:Type, annotation:Directive, injector:Injector) {
578+
dynamicallyCreateComponent(directiveBinding, injector:Injector) {
579579
this._shadowDomAppInjector = injector;
580-
this._dynamicallyCreatedComponentBinding = DirectiveBinding.createFromType(componentType, annotation);
580+
this._dynamicallyCreatedComponentBinding = directiveBinding;
581581
this._dynamicallyCreatedComponent = this._new(this._dynamicallyCreatedComponentBinding);
582582
return this._dynamicallyCreatedComponent;
583583
}
@@ -708,7 +708,7 @@ export class ElementInjector extends TreeNode {
708708

709709
_buildPropSetter(dep) {
710710
var view = this._getPreBuiltObjectByKeyId(StaticKeys.instance().viewId);
711-
var renderer = view.proto.renderer;
711+
var renderer = view.renderer;
712712
var index = this._proto.index;
713713
return function(v) {
714714
renderer.setElementProperty(view.render, index, dep.propSetterName, v);

modules/angular2/src/core/compiler/proto_view_factory.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,9 @@ import {ProtoElementInjector, DirectiveBinding} from './element_injector';
1313
@Injectable()
1414
export class ProtoViewFactory {
1515
_changeDetection:ChangeDetection;
16-
_renderer:renderApi.Renderer;
1716

18-
constructor(changeDetection:ChangeDetection, renderer:renderApi.Renderer) {
17+
constructor(changeDetection:ChangeDetection) {
1918
this._changeDetection = changeDetection;
20-
this._renderer = renderer;
2119
}
2220

2321
createProtoView(componentBinding:DirectiveBinding, renderProtoView: renderApi.ProtoViewDto, directives:List<DirectiveBinding>):AppProtoView {
@@ -30,7 +28,7 @@ export class ProtoViewFactory {
3028
'dummy', componentAnnotation.changeDetection
3129
);
3230
}
33-
var protoView = new AppProtoView(this._renderer, renderProtoView.render, protoChangeDetector);
31+
var protoView = new AppProtoView(renderProtoView.render, protoChangeDetector);
3432

3533
for (var i=0; i<renderProtoView.elementBinders.length; i++) {
3634
var renderElementBinder = renderProtoView.elementBinders[i];

0 commit comments

Comments
 (0)