Skip to content

Commit ba9fecd

Browse files
committed
refactor(render): use RenderElementRef in all renderer methods
BREAKING CHANGES: - Almost all methods in `Renderer` now take a `RenderElementRef` instead of a `ViewRef` + `boundElementIndex`. - These methods can be called with the `ElementRef` from the app side directly. Closes angular#2706 Related to angular#2476
1 parent 2c3c235 commit ba9fecd

File tree

13 files changed

+139
-127
lines changed

13 files changed

+139
-127
lines changed

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -771,9 +771,7 @@ export class ElementInjector extends TreeNode<ElementInjector> {
771771

772772
getComponent(): any { return this._strategy.getComponent(); }
773773

774-
getElementRef(): ElementRef {
775-
return new ElementRef(new ViewRef(this._preBuiltObjects.view), this._proto.index);
776-
}
774+
getElementRef(): ElementRef { return this._preBuiltObjects.view.elementRefs[this._proto.index]; }
777775

778776
getViewContainerRef(): ViewContainerRef {
779777
return new ViewContainerRef(this._preBuiltObjects.viewManager, this.getElementRef());

modules/angular2/src/core/compiler/element_ref.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
import {DOM} from 'angular2/src/dom/dom_adapter';
2-
import {normalizeBlank} from 'angular2/src/facade/lang';
2+
import {normalizeBlank, BaseException} from 'angular2/src/facade/lang';
33
import {ViewRef} from './view_ref';
44
import {resolveInternalDomView} from 'angular2/src/render/dom/view/view';
5+
import {RenderViewRef, RenderElementRef} from 'angular2/src/render/api';
56

67
/**
78
* @exportedAs angular2/view
89
*/
9-
export class ElementRef {
10+
export class ElementRef implements RenderElementRef {
1011
constructor(public parentView: ViewRef, public boundElementIndex: number) {}
1112

13+
get renderView() { return this.parentView.render; }
14+
// TODO(tbosch): remove this once Typescript supports declaring interfaces
15+
// that contain getters
16+
set renderView(value: any) { throw new BaseException('Abstract setter'); }
17+
1218
/**
1319
* Exposes the underlying DOM element.
1420
* (DEPRECATED way of accessing the DOM, replacement coming)

modules/angular2/src/core/compiler/view.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import {ElementBinder} from './element_binder';
2121
import {isPresent, isBlank, BaseException} from 'angular2/src/facade/lang';
2222
import * as renderApi from 'angular2/src/render/api';
2323
import {EventDispatcher} from 'angular2/src/render/api';
24+
import {ViewRef} from './view_ref';
25+
import {ElementRef} from './element_ref';
2426

2527
export class AppViewContainer {
2628
// The order in this list matches the DOM order.
@@ -40,6 +42,8 @@ export class AppView implements ChangeDispatcher, EventDispatcher {
4042
componentChildViews: List<AppView> = null;
4143
viewContainers: List<AppViewContainer>;
4244
preBuiltObjects: List<PreBuiltObjects> = null;
45+
elementRefs: List<ElementRef>;
46+
ref: ViewRef;
4347

4448
/**
4549
* The context against which data-binding expressions in this view are evaluated against.
@@ -58,6 +62,11 @@ export class AppView implements ChangeDispatcher, EventDispatcher {
5862
constructor(public renderer: renderApi.Renderer, public proto: AppProtoView,
5963
protoLocals: Map<string, any>) {
6064
this.viewContainers = ListWrapper.createFixedSize(this.proto.elementBinders.length);
65+
this.elementRefs = ListWrapper.createFixedSize(this.proto.elementBinders.length);
66+
this.ref = new ViewRef(this);
67+
for (var i = 0; i < this.elementRefs.length; i++) {
68+
this.elementRefs[i] = new ElementRef(this.ref, i);
69+
}
6170
this.locals = new Locals(null, MapWrapper.clone(protoLocals)); // TODO optimize this
6271
}
6372

@@ -100,14 +109,16 @@ export class AppView implements ChangeDispatcher, EventDispatcher {
100109
// dispatch to element injector or text nodes based on context
101110
notifyOnBinding(b: BindingRecord, currentValue: any): void {
102111
if (b.isElementProperty()) {
103-
this.renderer.setElementProperty(this.render, b.elementIndex, b.propertyName, currentValue);
112+
this.renderer.setElementProperty(this.elementRefs[b.elementIndex], b.propertyName,
113+
currentValue);
104114
} else if (b.isElementAttribute()) {
105-
this.renderer.setElementAttribute(this.render, b.elementIndex, b.propertyName, currentValue);
115+
this.renderer.setElementAttribute(this.elementRefs[b.elementIndex], b.propertyName,
116+
currentValue);
106117
} else if (b.isElementClass()) {
107-
this.renderer.setElementClass(this.render, b.elementIndex, b.propertyName, currentValue);
118+
this.renderer.setElementClass(this.elementRefs[b.elementIndex], b.propertyName, currentValue);
108119
} else if (b.isElementStyle()) {
109120
var unit = isPresent(b.propertyUnit) ? b.propertyUnit : '';
110-
this.renderer.setElementStyle(this.render, b.elementIndex, b.propertyName,
121+
this.renderer.setElementStyle(this.elementRefs[b.elementIndex], b.propertyName,
111122
`${currentValue}${unit}`);
112123
} else if (b.isTextNode()) {
113124
this.renderer.setText(this.render, b.elementIndex, currentValue);
@@ -134,7 +145,7 @@ export class AppView implements ChangeDispatcher, EventDispatcher {
134145
}
135146

136147
invokeElementMethod(elementIndex: number, methodName: string, args: List<any>) {
137-
this.renderer.invokeElementMethod(this.render, elementIndex, methodName, args);
148+
this.renderer.invokeElementMethod(this.elementRefs[elementIndex], methodName, args);
138149
}
139150

140151
// implementation of EventDispatcher#dispatchEvent

modules/angular2/src/core/compiler/view_container_ref.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export class ViewContainerRef {
2424
}
2525
}
2626

27-
get(index: number): ViewRef { return new ViewRef(this._getViews()[index]); }
27+
get(index: number): ViewRef { return this._getViews()[index].ref; }
2828

2929
get length(): number { return this._getViews().length; }
3030

modules/angular2/src/core/compiler/view_manager.ts

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export class AppViewManager {
2222
getComponentView(hostLocation: ElementRef): ViewRef {
2323
var hostView = internalView(hostLocation.parentView);
2424
var boundElementIndex = hostLocation.boundElementIndex;
25-
return new ViewRef(hostView.componentChildViews[boundElementIndex]);
25+
return hostView.componentChildViews[boundElementIndex].ref;
2626
}
2727

2828
getViewContainer(location: ElementRef): ViewContainerRef {
@@ -45,7 +45,7 @@ export class AppViewManager {
4545
if (isBlank(elementIndex)) {
4646
throw new BaseException(`Could not find variable ${variableName}`);
4747
}
48-
return new ElementRef(new ViewRef(componentView), elementIndex);
48+
return componentView.elementRefs[elementIndex];
4949
}
5050

5151
getComponent(hostLocation: ElementRef): any {
@@ -69,7 +69,7 @@ export class AppViewManager {
6969

7070
this._utils.hydrateRootHostView(hostView, injector);
7171
this._viewHydrateRecurse(hostView);
72-
return new ViewRef(hostView);
72+
return hostView.ref;
7373
}
7474

7575
destroyRootHostView(hostViewRef: ViewRef) {
@@ -98,14 +98,13 @@ export class AppViewManager {
9898

9999
var view = this._createPooledView(protoView);
100100

101-
this._renderer.attachViewInContainer(parentView.render, boundElementIndex, atIndex,
102-
view.render);
101+
this._renderer.attachViewInContainer(viewContainerLocation, atIndex, view.render);
103102
this._utils.attachViewInContainer(parentView, boundElementIndex, contextView,
104103
contextBoundElementIndex, atIndex, view);
105104
this._utils.hydrateViewInContainer(parentView, boundElementIndex, contextView,
106105
contextBoundElementIndex, atIndex, injector);
107106
this._viewHydrateRecurse(view);
108-
return new ViewRef(view);
107+
return view.ref;
109108
}
110109

111110
destroyViewInContainer(viewContainerLocation: ElementRef, atIndex: number) {
@@ -126,8 +125,7 @@ export class AppViewManager {
126125
// Right now we are destroying any special
127126
// context view that might have been used.
128127
this._utils.attachViewInContainer(parentView, boundElementIndex, null, null, atIndex, view);
129-
this._renderer.attachViewInContainer(parentView.render, boundElementIndex, atIndex,
130-
view.render);
128+
this._renderer.attachViewInContainer(viewContainerLocation, atIndex, view.render);
131129
return viewRef;
132130
}
133131

@@ -137,9 +135,8 @@ export class AppViewManager {
137135
var viewContainer = parentView.viewContainers[boundElementIndex];
138136
var view = viewContainer.views[atIndex];
139137
this._utils.detachViewInContainer(parentView, boundElementIndex, atIndex);
140-
this._renderer.detachViewInContainer(parentView.render, boundElementIndex, atIndex,
141-
view.render);
142-
return new ViewRef(view);
138+
this._renderer.detachViewInContainer(viewContainerLocation, atIndex, view.render);
139+
return view.ref;
143140
}
144141

145142
_createPooledView(protoView: viewModule.AppProtoView): viewModule.AppView {
@@ -160,7 +157,7 @@ export class AppViewManager {
160157
var binder = binders[binderIdx];
161158
if (binder.hasStaticComponent()) {
162159
var childView = this._createPooledView(binder.nestedProtoView);
163-
this._renderer.attachComponentView(view.render, binderIdx, childView.render);
160+
this._renderer.attachComponentView(view.elementRefs[binderIdx], childView.render);
164161
this._utils.attachComponentView(view, binderIdx, childView);
165162
}
166163
}
@@ -179,14 +176,15 @@ export class AppViewManager {
179176
var view = viewContainer.views[atIndex];
180177
this._viewDehydrateRecurse(view, false);
181178
this._utils.detachViewInContainer(parentView, boundElementIndex, atIndex);
182-
this._renderer.detachViewInContainer(parentView.render, boundElementIndex, atIndex,
179+
this._renderer.detachViewInContainer(parentView.elementRefs[boundElementIndex], atIndex,
183180
view.render);
184181
this._destroyPooledView(view);
185182
}
186183

187184
_destroyComponentView(hostView, boundElementIndex, componentView) {
188185
this._viewDehydrateRecurse(componentView, false);
189-
this._renderer.detachComponentView(hostView.render, boundElementIndex, componentView.render);
186+
this._renderer.detachComponentView(hostView.elementRefs[boundElementIndex],
187+
componentView.render);
190188
this._utils.detachComponentView(hostView, boundElementIndex);
191189
this._destroyPooledView(componentView);
192190
}

modules/angular2/src/forms/directives/shared.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,5 @@ function _throwError(dir: NgControl, message: string): void {
4949

5050
export function setProperty(renderer: Renderer, elementRef: ElementRef, propName: string,
5151
propValue: any) {
52-
renderer.setElementProperty(elementRef.parentView.render, elementRef.boundElementIndex, propName,
53-
propValue);
54-
}
52+
renderer.setElementProperty(elementRef, propName, propValue);
53+
}

modules/angular2/src/render/api.ts

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,11 @@ export class RenderCompiler {
306306
compile(template: ViewDefinition): Promise<ProtoViewDto> { return null; }
307307
}
308308

309+
export interface RenderElementRef {
310+
renderView: RenderViewRef;
311+
boundElementIndex: number;
312+
}
313+
309314
export class Renderer {
310315
/**
311316
* Creates a root host view that includes the given element.
@@ -333,29 +338,25 @@ export class Renderer {
333338
/**
334339
* Attaches a componentView into the given hostView at the given element
335340
*/
336-
attachComponentView(hostViewRef: RenderViewRef, elementIndex: number,
337-
componentViewRef: RenderViewRef) {}
341+
attachComponentView(location: RenderElementRef, componentViewRef: RenderViewRef) {}
338342

339343
/**
340344
* Detaches a componentView into the given hostView at the given element
341345
*/
342-
detachComponentView(hostViewRef: RenderViewRef, boundElementIndex: number,
343-
componentViewRef: RenderViewRef) {}
346+
detachComponentView(location: RenderElementRef, componentViewRef: RenderViewRef) {}
344347

345348
/**
346349
* Attaches a view into a ViewContainer (in the given parentView at the given element) at the
347350
* given index.
348351
*/
349-
attachViewInContainer(parentViewRef: RenderViewRef, boundElementIndex: number, atIndex: number,
350-
viewRef: RenderViewRef) {}
352+
attachViewInContainer(location: RenderElementRef, atIndex: number, viewRef: RenderViewRef) {}
351353

352354
/**
353355
* Detaches a view into a ViewContainer (in the given parentView at the given element) at the
354356
* given index.
355357
*/
356358
// TODO(tbosch): this should return a promise as it can be animated!
357-
detachViewInContainer(parentViewRef: RenderViewRef, boundElementIndex: number, atIndex: number,
358-
viewRef: RenderViewRef) {}
359+
detachViewInContainer(location: RenderElementRef, atIndex: number, viewRef: RenderViewRef) {}
359360

360361
/**
361362
* Hydrates a view after it has been attached. Hydration/dehydration is used for reusing views
@@ -372,32 +373,27 @@ export class Renderer {
372373
/**
373374
* Sets a property on an element.
374375
*/
375-
setElementProperty(viewRef: RenderViewRef, elementIndex: number, propertyName: string,
376-
propertyValue: any) {}
376+
setElementProperty(location: RenderElementRef, propertyName: string, propertyValue: any) {}
377377

378378
/**
379379
* Sets an attribute on an element.
380380
*/
381-
setElementAttribute(viewRef: RenderViewRef, elementIndex: number, attributeName: string,
382-
attributeValue: string) {}
381+
setElementAttribute(location: RenderElementRef, attributeName: string, attributeValue: string) {}
383382

384383
/**
385384
* Sets a class on an element.
386385
*/
387-
setElementClass(viewRef: RenderViewRef, elementIndex: number, className: string, isAdd: boolean) {
388-
}
386+
setElementClass(location: RenderElementRef, className: string, isAdd: boolean) {}
389387

390388
/**
391389
* Sets a style on an element.
392390
*/
393-
setElementStyle(viewRef: RenderViewRef, elementIndex: number, styleName: string,
394-
styleValue: string) {}
391+
setElementStyle(location: RenderElementRef, styleName: string, styleValue: string) {}
395392

396393
/**
397394
* Calls a method on an element.
398395
*/
399-
invokeElementMethod(viewRef: RenderViewRef, elementIndex: number, methodName: string,
400-
args: List<any>) {}
396+
invokeElementMethod(location: RenderElementRef, methodName: string, args: List<any>) {}
401397

402398
/**
403399
* Sets the value of a text node.

0 commit comments

Comments
 (0)