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 #2706
Related to #2476
This commit is contained in:
Tobias Bosch
2015-06-23 11:21:56 -07:00
parent 2c3c235969
commit ba9fecd068
13 changed files with 139 additions and 127 deletions
@@ -51,7 +51,6 @@ import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref';
import {ProtoViewRef} from 'angular2/src/core/compiler/view_ref';
import {ElementRef} from 'angular2/src/core/compiler/element_ref';
import {DynamicChangeDetector, ChangeDetectorRef, Parser, Lexer} from 'angular2/change_detection';
import {Renderer} from 'angular2/src/render/api';
import {QueryList} from 'angular2/src/core/compiler/query_list';
@proxy
@@ -59,14 +58,25 @@ import {QueryList} from 'angular2/src/core/compiler/query_list';
class DummyView extends SpyObject {
componentChildViews;
changeDetector;
constructor() {
super();
elementRefs;
constructor(elementCount = 0) {
super(AppView);
this.componentChildViews = [];
this.changeDetector = null;
this.elementRefs = ListWrapper.createFixedSize(elementCount);
for (var i=0; i<elementCount; i++) {
this.elementRefs[i] = new DummyElementRef();
}
}
noSuchMethod(m) { return super.noSuchMethod(m); }
}
@proxy
@IMPLEMENTS(ElementRef)
class DummyElementRef extends SpyObject {
constructor() { super(ElementRef); }
noSuchMethod(m) { return super.noSuchMethod(m); }
}
class SimpleDirective {}
@@ -225,7 +235,7 @@ class TestNode extends TreeNode<TestNode> {
}
export function main() {
var defaultPreBuiltObjects = new PreBuiltObjects(null, null, null);
var defaultPreBuiltObjects = new PreBuiltObjects(null, <any>new DummyView(1), null);
var appInjector = Injector.resolveAndCreate([]);
// An injector with more than 10 bindings will switch to the dynamic strategy
@@ -893,7 +903,7 @@ export function main() {
describe("refs", () => {
it("should inject ElementRef", () => {
var inj = injector(ListWrapper.concat([NeedsElementRef], extraBindings));
expect(inj.get(NeedsElementRef).elementRef).toBeAnInstanceOf(ElementRef);
expect(inj.get(NeedsElementRef).elementRef).toBe(defaultPreBuiltObjects.view.elementRefs[0]);
});
it('should inject ChangeDetectorRef', () => {
@@ -1005,7 +1015,7 @@ export function main() {
var inj = injector(ListWrapper.concat(dirs, extraBindings), null,
false, preBuildObjects, null, dirVariableBindings);
expect(inj.get(NeedsQueryByVarBindings).query.first).toBeAnInstanceOf(ElementRef);
expect(inj.get(NeedsQueryByVarBindings).query.first).toBe(defaultPreBuiltObjects.view.elementRefs[0]);
});
it('should contain directives on the same injector when querying by variable bindings' +
@@ -1139,14 +1149,3 @@ class ContextWithHandler {
handler;
constructor(handler) { this.handler = handler; }
}
class FakeRenderer extends Renderer {
log: List<List<any>>;
constructor() {
super();
this.log = [];
}
setElementProperty(viewRef, elementIndex, propertyName, value) {
this.log.push([viewRef, elementIndex, propertyName, value]);
}
}
@@ -292,13 +292,13 @@ export function main() {
it('should attach the view', () => {
var contextView = createView();
manager.createViewInContainer(elementRef(wrapView(parentView), 0), 0,
wrapPv(childProtoView),
var elRef = elementRef(wrapView(parentView), 0);
manager.createViewInContainer(elRef, 0, wrapPv(childProtoView),
elementRef(wrapView(contextView), 1), null);
expect(utils.spy('attachViewInContainer'))
.toHaveBeenCalledWith(parentView, 0, contextView, 1, 0, createdViews[0]);
expect(renderer.spy('attachViewInContainer'))
.toHaveBeenCalledWith(parentView.render, 0, 0, createdViews[0].render);
.toHaveBeenCalledWith(elRef, 0, createdViews[0].render);
});
it('should hydrate the view', () => {
@@ -349,10 +349,11 @@ export function main() {
});
it('should detach', () => {
manager.destroyViewInContainer(elementRef(wrapView(parentView), 0), 0);
var elRef = elementRef(wrapView(parentView), 0);
manager.destroyViewInContainer(elRef, 0);
expect(utils.spy('detachViewInContainer')).toHaveBeenCalledWith(parentView, 0, 0);
expect(renderer.spy('detachViewInContainer'))
.toHaveBeenCalledWith(parentView.render, 0, 0, childView.render);
.toHaveBeenCalledWith(elRef, 0, childView.render);
});
it('should return the view to the pool', () => {
@@ -381,7 +382,7 @@ export function main() {
manager.destroyRootHostView(wrapView(parentView));
expect(utils.spy('detachViewInContainer')).toHaveBeenCalledWith(parentView, 0, 0);
expect(renderer.spy('detachViewInContainer'))
.toHaveBeenCalledWith(parentView.render, 0, 0, childView.render);
.toHaveBeenCalledWith(parentView.elementRefs[0], 0, childView.render);
});
it('should return the view to the pool', () => {
@@ -16,7 +16,7 @@ import {
import {MapWrapper} from 'angular2/src/facade/collection';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {DomTestbed, TestView} from './dom_testbed';
import {DomTestbed, TestView, elRef} from './dom_testbed';
import {ViewDefinition, DirectiveMetadata, RenderViewRef} from 'angular2/src/render/api';
@@ -106,20 +106,20 @@ export function main() {
var cmpView = tb.createComponentView(rootView.viewRef, 0, protoViewDtos[1]);
var el = DOM.childNodes(tb.rootEl)[0];
tb.renderer.setElementProperty(cmpView.viewRef, 0, 'value', 'hello');
tb.renderer.setElementProperty(elRef(cmpView.viewRef, 0), 'value', 'hello');
expect(el.value).toEqual('hello');
tb.renderer.setElementClass(cmpView.viewRef, 0, 'a', true);
tb.renderer.setElementClass(elRef(cmpView.viewRef, 0), 'a', true);
expect(DOM.childNodes(tb.rootEl)[0].value).toEqual('hello');
tb.renderer.setElementClass(cmpView.viewRef, 0, 'a', false);
tb.renderer.setElementClass(elRef(cmpView.viewRef, 0), 'a', false);
expect(DOM.hasClass(el, 'a')).toBe(false);
tb.renderer.setElementStyle(cmpView.viewRef, 0, 'width', '10px');
tb.renderer.setElementStyle(elRef(cmpView.viewRef, 0), 'width', '10px');
expect(DOM.getStyle(el, 'width')).toEqual('10px');
tb.renderer.setElementStyle(cmpView.viewRef, 0, 'width', null);
tb.renderer.setElementStyle(elRef(cmpView.viewRef, 0), 'width', null);
expect(DOM.getStyle(el, 'width')).toEqual('');
tb.renderer.setElementAttribute(cmpView.viewRef, 0, 'someAttr', 'someValue');
tb.renderer.setElementAttribute(elRef(cmpView.viewRef, 0), 'someAttr', 'someValue');
expect(DOM.getAttribute(el, 'some-attr')).toEqual('someValue');
async.done();
@@ -141,7 +141,7 @@ export function main() {
var views = tb.createRootViews(protoViewDtos);
var componentView = views[1];
tb.renderer.invokeElementMethod(componentView.viewRef, 0, 'setAttribute',
tb.renderer.invokeElementMethod(elRef(componentView.viewRef, 0), 'setAttribute',
['a', 'b']);
expect(DOM.getAttribute(DOM.childNodes(tb.rootEl)[0], 'a')).toEqual('b');
@@ -11,7 +11,8 @@ import {
ProtoViewDto,
ViewDefinition,
EventDispatcher,
DirectiveMetadata
DirectiveMetadata,
RenderElementRef
} from 'angular2/src/render/api';
import {resolveInternalDomView} from 'angular2/src/render/dom/view/view';
import {el, dispatchEvent} from 'angular2/test_lib';
@@ -28,6 +29,13 @@ export class TestView {
}
}
export function elRef(renderView: RenderViewRef, boundElementIndex: number) {
return new TestRenderElementRef(renderView, boundElementIndex);
}
class TestRenderElementRef implements RenderElementRef {
constructor(public renderView: RenderViewRef, public boundElementIndex: number) {}
}
class LoggingEventDispatcher implements EventDispatcher {
log: List<List<any>>;
@@ -85,7 +93,7 @@ export class DomTestbed {
createComponentView(parentViewRef: RenderViewRef, boundElementIndex: number,
componentProtoView: ProtoViewDto): TestView {
var componentViewRef = this.renderer.createView(componentProtoView.render);
this.renderer.attachComponentView(parentViewRef, boundElementIndex, componentViewRef);
this.renderer.attachComponentView(elRef(parentViewRef, boundElementIndex), componentViewRef);
this.renderer.hydrateView(componentViewRef);
return this._createTestView(componentViewRef);
}
@@ -104,13 +112,13 @@ export class DomTestbed {
destroyComponentView(parentViewRef: RenderViewRef, boundElementIndex: number,
componentView: RenderViewRef) {
this.renderer.dehydrateView(componentView);
this.renderer.detachComponentView(parentViewRef, boundElementIndex, componentView);
this.renderer.detachComponentView(elRef(parentViewRef, boundElementIndex), componentView);
}
createViewInContainer(parentViewRef: RenderViewRef, boundElementIndex: number, atIndex: number,
protoView: ProtoViewDto): TestView {
var viewRef = this.renderer.createView(protoView.render);
this.renderer.attachViewInContainer(parentViewRef, boundElementIndex, atIndex, viewRef);
this.renderer.attachViewInContainer(elRef(parentViewRef, boundElementIndex), atIndex, viewRef);
this.renderer.hydrateView(viewRef);
return this._createTestView(viewRef);
}
@@ -118,7 +126,7 @@ export class DomTestbed {
destroyViewInContainer(parentViewRef: RenderViewRef, boundElementIndex: number, atIndex: number,
viewRef: RenderViewRef) {
this.renderer.dehydrateView(viewRef);
this.renderer.detachViewInContainer(parentViewRef, boundElementIndex, atIndex, viewRef);
this.renderer.detachViewInContainer(elRef(parentViewRef, boundElementIndex), atIndex, viewRef);
this.renderer.destroyView(viewRef);
}
@@ -32,7 +32,7 @@ import {
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
import {DomTestbed} from './dom_testbed';
import {DomTestbed, elRef} from './dom_testbed';
export function main() {
describe('ShadowDom integration tests', function() {
@@ -425,17 +425,21 @@ export function main() {
expect(tb.rootEl).toHaveText('(TAB(0))');
tb.renderer.dehydrateView(tabChildView.viewRef);
tb.renderer.detachViewInContainer(tab1View.viewRef, 0, 0, tabChildView.viewRef);
tb.renderer.detachViewInContainer(elRef(tab1View.viewRef, 0), 0,
tabChildView.viewRef);
tb.renderer.attachViewInContainer(tab2View.viewRef, 0, 0, tabChildView.viewRef);
tb.renderer.attachViewInContainer(elRef(tab2View.viewRef, 0), 0,
tabChildView.viewRef);
tb.renderer.hydrateView(tabChildView.viewRef);
expect(tb.rootEl).toHaveText('(TAB(1))');
tb.renderer.dehydrateView(tabChildView.viewRef);
tb.renderer.detachViewInContainer(tab2View.viewRef, 0, 0, tabChildView.viewRef);
tb.renderer.detachViewInContainer(elRef(tab2View.viewRef, 0), 0,
tabChildView.viewRef);
tb.renderer.attachViewInContainer(tab3View.viewRef, 0, 0, tabChildView.viewRef);
tb.renderer.attachViewInContainer(elRef(tab3View.viewRef, 0), 0,
tabChildView.viewRef);
tb.renderer.hydrateView(tabChildView.viewRef);
expect(tb.rootEl).toHaveText('(TAB(2))');