refactor(render): cleanup access to native dom elements
BREAKING CHANGES: - rename `ElementRef.domElement` to `ElementRef.nativeElement` - add `Renderer.getNativeElementSync` to make the app side less dependent on the dom renderer. - don’t use `ElementRef.nativeElement` in directives but use the methods on `Renderer` directly. - Removed `ElementRef.setAttribute`. Use `Renderer.setElementAttribute` instead. Closes #2712 Last part of #2476 Closes #2476
This commit is contained in:
		
							parent
							
								
									5c9e53a25e
								
							
						
					
					
						commit
						c8bdacb195
					
				| @ -1,2 +1,2 @@ | ||||
| export * from './src/debug/debug_element'; | ||||
| export {inspectDomElement, ELEMENT_PROBE_CONFIG} from './src/debug/debug_element_view_listener'; | ||||
| export {inspectNativeElement, ELEMENT_PROBE_CONFIG} from './src/debug/debug_element_view_listener'; | ||||
|  | ||||
| @ -56,7 +56,6 @@ import {AppViewListener} from 'angular2/src/core/compiler/view_listener'; | ||||
| import {ProtoViewFactory} from 'angular2/src/core/compiler/proto_view_factory'; | ||||
| import {Renderer, RenderCompiler} from 'angular2/src/render/api'; | ||||
| import {DomRenderer, DOCUMENT_TOKEN} from 'angular2/src/render/dom/dom_renderer'; | ||||
| import {resolveInternalDomView} from 'angular2/src/render/dom/view/view'; | ||||
| import {DefaultDomCompiler} from 'angular2/src/render/dom/compiler/compiler'; | ||||
| import {internalView} from 'angular2/src/core/compiler/view_ref'; | ||||
| 
 | ||||
| @ -85,10 +84,7 @@ function _injectorBindings(appComponentType): List<Type | Binding | List<any>> { | ||||
|               // TODO(rado): investigate whether to support bindings on root component.
 | ||||
|               return dynamicComponentLoader.loadAsRoot(appComponentType, null, injector) | ||||
|                   .then((componentRef) => { | ||||
|                     var domView = resolveInternalDomView(componentRef.hostView.render); | ||||
|                     // We need to do this here to ensure that we create Testability and
 | ||||
|                     // it's ready on the window for users.
 | ||||
|                     registry.registerApplication(domView.boundElements[0].element, testability); | ||||
|                     registry.registerApplication(componentRef.location.nativeElement, testability); | ||||
| 
 | ||||
|                     return componentRef; | ||||
|                   }); | ||||
|  | ||||
| @ -36,7 +36,7 @@ export class DynamicComponentLoader { | ||||
|         .then(hostProtoViewRef => { | ||||
|           var hostViewRef = | ||||
|               this._viewManager.createRootHostView(hostProtoViewRef, overrideSelector, injector); | ||||
|           var newLocation = new ElementRef(hostViewRef, 0); | ||||
|           var newLocation = this._viewManager.getHostElement(hostViewRef); | ||||
|           var component = this._viewManager.getComponent(newLocation); | ||||
| 
 | ||||
|           var dispose = () => { this._viewManager.destroyRootHostView(hostViewRef); }; | ||||
| @ -68,7 +68,7 @@ export class DynamicComponentLoader { | ||||
|           var viewContainer = this._viewManager.getViewContainer(location); | ||||
|           var hostViewRef = | ||||
|               viewContainer.create(hostProtoViewRef, viewContainer.length, null, injector); | ||||
|           var newLocation = new ElementRef(hostViewRef, 0); | ||||
|           var newLocation = this._viewManager.getHostElement(hostViewRef); | ||||
|           var component = this._viewManager.getComponent(newLocation); | ||||
| 
 | ||||
|           var dispose = () => { | ||||
|  | ||||
| @ -1,41 +1,22 @@ | ||||
| import {DOM} from 'angular2/src/dom/dom_adapter'; | ||||
| import {normalizeBlank, BaseException} from 'angular2/src/facade/lang'; | ||||
| import {BaseException} from 'angular2/src/facade/lang'; | ||||
| import {ViewRef} from './view_ref'; | ||||
| import {resolveInternalDomView} from 'angular2/src/render/dom/view/view'; | ||||
| import {RenderViewRef, RenderElementRef} from 'angular2/src/render/api'; | ||||
| import {RenderViewRef, RenderElementRef, Renderer} from 'angular2/src/render/api'; | ||||
| 
 | ||||
| /** | ||||
|  * @exportedAs angular2/view | ||||
|  */ | ||||
| export class ElementRef implements RenderElementRef { | ||||
|   constructor(public parentView: ViewRef, public boundElementIndex: number) {} | ||||
|   constructor(public parentView: ViewRef, public boundElementIndex: number, | ||||
|               private _renderer: Renderer) {} | ||||
| 
 | ||||
|   get renderView() { return this.parentView.render; } | ||||
|   get renderView(): RenderViewRef { return this.parentView.render; } | ||||
|   // TODO(tbosch): remove this once Typescript supports declaring interfaces
 | ||||
|   // that contain getters
 | ||||
|   set renderView(value: any) { throw new BaseException('Abstract setter'); } | ||||
|   set renderView(viewRef: RenderViewRef) { throw new BaseException('Abstract setter'); } | ||||
| 
 | ||||
|   /** | ||||
|    * Exposes the underlying DOM element. | ||||
|    * (DEPRECATED way of accessing the DOM, replacement coming) | ||||
|    * Exposes the underlying native element. | ||||
|    * Attention: This won't work in a webworker scenario! | ||||
|    */ | ||||
|   // TODO(tbosch): Here we expose the real DOM element.
 | ||||
|   // We need a more general way to read/write to the DOM element
 | ||||
|   // via a proper abstraction in the render layer
 | ||||
|   get domElement() { | ||||
|     return resolveInternalDomView(this.parentView.render) | ||||
|         .boundElements[this.boundElementIndex] | ||||
|         .element; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Gets an attribute from the underlying DOM element. | ||||
|    * (DEPRECATED way of accessing the DOM, replacement coming) | ||||
|    */ | ||||
|   // TODO(tbosch): Here we expose the real DOM element.
 | ||||
|   // We need a more general way to read/write to the DOM element
 | ||||
|   // via a proper abstraction in the render layer
 | ||||
|   getAttribute(name: string): string { | ||||
|     return normalizeBlank(DOM.getAttribute(this.domElement, name)); | ||||
|   } | ||||
|   get nativeElement(): any { return this._renderer.getNativeElementSync(this); } | ||||
| } | ||||
|  | ||||
| @ -65,7 +65,7 @@ export class AppView implements ChangeDispatcher, EventDispatcher { | ||||
|     this.elementRefs = ListWrapper.createFixedSize(this.proto.elementBinders.length); | ||||
|     this.ref = new ViewRef(this); | ||||
|     for (var i = 0; i < this.elementRefs.length; i++) { | ||||
|       this.elementRefs[i] = new ElementRef(this.ref, i); | ||||
|       this.elementRefs[i] = new ElementRef(this.ref, i, renderer); | ||||
|     } | ||||
|     this.locals = new Locals(null, MapWrapper.clone(protoLocals));  // TODO optimize this
 | ||||
|   } | ||||
|  | ||||
| @ -30,6 +30,10 @@ export class AppViewManager { | ||||
|     return hostView.elementInjectors[location.boundElementIndex].getViewContainerRef(); | ||||
|   } | ||||
| 
 | ||||
|   getHostElement(hostViewRef: ViewRef): ElementRef { | ||||
|     return internalView(hostViewRef).elementRefs[0]; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Returns an ElementRef for the element with the given variable name | ||||
|    * in the component view of the component at the provided ElementRef. | ||||
|  | ||||
| @ -165,7 +165,7 @@ export class AppViewManagerUtils { | ||||
|     if (isPresent(elementInjector.getDirectiveVariableBindings())) { | ||||
|       MapWrapper.forEach(elementInjector.getDirectiveVariableBindings(), (directiveIndex, name) => { | ||||
|         if (isBlank(directiveIndex)) { | ||||
|           view.locals.set(name, elementInjector.getElementRef().domElement); | ||||
|           view.locals.set(name, elementInjector.getElementRef().nativeElement); | ||||
|         } else { | ||||
|           view.locals.set(name, elementInjector.getDirectiveAtIndex(directiveIndex)); | ||||
|         } | ||||
|  | ||||
| @ -8,8 +8,6 @@ import {AppView} from 'angular2/src/core/compiler/view'; | ||||
| import {internalView} from 'angular2/src/core/compiler/view_ref'; | ||||
| import {ElementRef} from 'angular2/src/core/compiler/element_ref'; | ||||
| 
 | ||||
| import {resolveInternalDomView} from 'angular2/src/render/dom/view/view'; | ||||
| 
 | ||||
| /** | ||||
|  * @exportedAs angular2/test | ||||
|  * | ||||
| @ -35,13 +33,9 @@ export class DebugElement { | ||||
|     return this._elementInjector.getComponent(); | ||||
|   } | ||||
| 
 | ||||
|   get domElement(): any { | ||||
|     return resolveInternalDomView(this._parentView.render) | ||||
|         .boundElements[this._boundElementIndex] | ||||
|         .element; | ||||
|   } | ||||
|   get nativeElement(): any { return this.elementRef.nativeElement; } | ||||
| 
 | ||||
|   get elementRef(): ElementRef { return this._elementInjector.getElementRef(); } | ||||
|   get elementRef(): ElementRef { return this._parentView.elementRefs[this._boundElementIndex]; } | ||||
| 
 | ||||
|   getDirectiveInstance(directiveIndex: number): any { | ||||
|     return this._elementInjector.getDirectiveAtIndex(directiveIndex); | ||||
| @ -192,7 +186,7 @@ export class By { | ||||
|   static all(): Function { return (debugElement) => true; } | ||||
| 
 | ||||
|   static css(selector: string): Function { | ||||
|     return (debugElement) => { return DOM.elementMatches(debugElement.domElement, selector); }; | ||||
|     return (debugElement) => { return DOM.elementMatches(debugElement.nativeElement, selector); }; | ||||
|   } | ||||
|   static directive(type: Type): Function { | ||||
|     return (debugElement) => { return debugElement.hasDirective(type); }; | ||||
|  | ||||
| @ -10,7 +10,7 @@ import {Injectable, bind, Binding} from 'angular2/di'; | ||||
| import {AppViewListener} from 'angular2/src/core/compiler/view_listener'; | ||||
| import {AppView} from 'angular2/src/core/compiler/view'; | ||||
| import {DOM} from 'angular2/src/dom/dom_adapter'; | ||||
| import {resolveInternalDomView} from 'angular2/src/render/dom/view/view'; | ||||
| import {Renderer} from 'angular2/src/render/api'; | ||||
| import {DebugElement} from './debug_element'; | ||||
| 
 | ||||
| const NG_ID_PROPERTY = 'ngid'; | ||||
| @ -41,7 +41,7 @@ function _getElementId(element): List<number> { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export function inspectDomElement(element): DebugElement { | ||||
| export function inspectNativeElement(element): DebugElement { | ||||
|   var elId = _getElementId(element); | ||||
|   if (isPresent(elId)) { | ||||
|     var view = _allViewsById.get(elId[0]); | ||||
| @ -54,15 +54,16 @@ export function inspectDomElement(element): DebugElement { | ||||
| 
 | ||||
| @Injectable() | ||||
| export class DebugElementViewListener implements AppViewListener { | ||||
|   constructor() { DOM.setGlobalVar(INSPECT_GLOBAL_NAME, inspectDomElement); } | ||||
|   constructor(private _renderer: Renderer) { | ||||
|     DOM.setGlobalVar(INSPECT_GLOBAL_NAME, inspectNativeElement); | ||||
|   } | ||||
| 
 | ||||
|   viewCreated(view: AppView) { | ||||
|     var viewId = _nextId++; | ||||
|     _allViewsById.set(viewId, view); | ||||
|     _allIdsByView.set(view, viewId); | ||||
|     var renderView = resolveInternalDomView(view.render); | ||||
|     for (var i = 0; i < renderView.boundElements.length; i++) { | ||||
|       _setElementId(renderView.boundElements[i].element, [viewId, i]); | ||||
|     for (var i = 0; i < view.elementRefs.length; i++) { | ||||
|       _setElementId(this._renderer.getNativeElementSync(view.elementRefs[i]), [viewId, i]); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|  | ||||
| @ -2,17 +2,15 @@ import {Directive, onCheck} from 'angular2/annotations'; | ||||
| import {ElementRef} from 'angular2/core'; | ||||
| import {PipeRegistry} from 'angular2/src/change_detection/pipes/pipe_registry'; | ||||
| import {isPresent} from 'angular2/src/facade/lang'; | ||||
| import {DOM} from 'angular2/src/dom/dom_adapter'; | ||||
| import {Renderer} from 'angular2/src/render/api'; | ||||
| 
 | ||||
| @Directive({selector: '[class]', lifecycle: [onCheck], properties: ['rawClass: class']}) | ||||
| export class CSSClass { | ||||
|   _domEl; | ||||
|   _pipe; | ||||
|   _rawClass; | ||||
| 
 | ||||
|   constructor(private _pipeRegistry: PipeRegistry, ngEl: ElementRef) { | ||||
|     this._domEl = ngEl.domElement; | ||||
|   } | ||||
|   constructor(private _pipeRegistry: PipeRegistry, private _ngEl: ElementRef, | ||||
|               private _renderer: Renderer) {} | ||||
| 
 | ||||
|   set rawClass(v) { | ||||
|     this._rawClass = v; | ||||
| @ -20,11 +18,7 @@ export class CSSClass { | ||||
|   } | ||||
| 
 | ||||
|   _toggleClass(className, enabled): void { | ||||
|     if (enabled) { | ||||
|       DOM.addClass(this._domEl, className); | ||||
|     } else { | ||||
|       DOM.removeClass(this._domEl, className); | ||||
|     } | ||||
|     this._renderer.setElementClass(this._ngEl, className, enabled); | ||||
|   } | ||||
| 
 | ||||
|   onCheck() { | ||||
| @ -38,7 +32,7 @@ export class CSSClass { | ||||
|       diff.forEachChangedItem((record) => { this._toggleClass(record.key, record.currentValue); }); | ||||
|       diff.forEachRemovedItem((record) => { | ||||
|         if (record.previousValue) { | ||||
|           DOM.removeClass(this._domEl, record.key); | ||||
|           this._toggleClass(record.key, false); | ||||
|         } | ||||
|       }); | ||||
|     } | ||||
|  | ||||
| @ -370,6 +370,12 @@ export class Renderer { | ||||
|    */ | ||||
|   dehydrateView(viewRef: RenderViewRef) {} | ||||
| 
 | ||||
|   /** | ||||
|    * Returns the native element at the given location. | ||||
|    * Attention: In a WebWorker scenario, this should always return null! | ||||
|    */ | ||||
|   getNativeElementSync(location: RenderElementRef): any { return null; } | ||||
| 
 | ||||
|   /** | ||||
|    * Sets a property on an element. | ||||
|    */ | ||||
|  | ||||
| @ -53,6 +53,12 @@ export class DomRenderer extends Renderer { | ||||
|     // noop for now
 | ||||
|   } | ||||
| 
 | ||||
|   getNativeElementSync(location: RenderElementRef) { | ||||
|     return resolveInternalDomView(location.renderView) | ||||
|         .boundElements[location.boundElementIndex] | ||||
|         .element; | ||||
|   } | ||||
| 
 | ||||
|   attachComponentView(location: RenderElementRef, componentViewRef: RenderViewRef) { | ||||
|     var hostView = resolveInternalDomView(location.renderView); | ||||
|     var componentView = resolveInternalDomView(componentViewRef); | ||||
|  | ||||
| @ -4,10 +4,10 @@ import {ElementRef} from 'angular2/core'; | ||||
| import {StringMap, StringMapWrapper} from 'angular2/src/facade/collection'; | ||||
| 
 | ||||
| import {isPresent} from 'angular2/src/facade/lang'; | ||||
| import {DOM} from 'angular2/src/dom/dom_adapter'; | ||||
| 
 | ||||
| import {Router} from './router'; | ||||
| import {Location} from './location'; | ||||
| import {Renderer} from 'angular2/src/render/api'; | ||||
| 
 | ||||
| /** | ||||
|  * The RouterLink directive lets you link to specific parts of your app. | ||||
| @ -37,7 +37,6 @@ import {Location} from './location'; | ||||
|   host: {'(^click)': 'onClick()'} | ||||
| }) | ||||
| export class RouterLink { | ||||
|   private _domEl; | ||||
|   private _route: string; | ||||
|   private _params: StringMap<string, string>; | ||||
| 
 | ||||
| @ -46,8 +45,8 @@ export class RouterLink { | ||||
|   // the url passed to the router navigation.
 | ||||
|   _navigationHref: string; | ||||
| 
 | ||||
|   constructor(elementRef: ElementRef, private _router: Router, private _location: Location) { | ||||
|     this._domEl = elementRef.domElement; | ||||
|   constructor(private _elementRef: ElementRef, private _router: Router, private _location: Location, | ||||
|               private _renderer: Renderer) { | ||||
|     this._params = StringMapWrapper.create(); | ||||
|   } | ||||
| 
 | ||||
| @ -66,7 +65,7 @@ export class RouterLink { | ||||
|       this._visibleHref = this._location.normalizeAbsolutely(this._navigationHref); | ||||
|       // Keeping the link on the element to support contextual menu `copy link`
 | ||||
|       // and other in-browser affordances.
 | ||||
|       DOM.setAttribute(this._domEl, 'href', this._visibleHref); | ||||
|       this._renderer.setElementAttribute(this._elementRef, 'href', this._visibleHref); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -24,7 +24,7 @@ export class Ruler { | ||||
|   constructor(domAdapter: DomAdapter) { this.domAdapter = domAdapter; } | ||||
| 
 | ||||
|   measure(el: ElementRef): Promise<Rectangle> { | ||||
|     var clntRect = <any>this.domAdapter.getBoundingClientRect(el.domElement); | ||||
|     var clntRect = <any>this.domAdapter.getBoundingClientRect(el.nativeElement); | ||||
| 
 | ||||
|     // even if getBoundingClientRect is synchronous we use async API in preparation for further
 | ||||
|     // changes
 | ||||
|  | ||||
| @ -41,7 +41,7 @@ export function main() { | ||||
| 
 | ||||
|                         loader.loadIntoLocation(DynamicallyLoaded, tc.elementRef, 'loc') | ||||
|                             .then(ref => { | ||||
|                               expect(tc.domElement).toHaveText("Location;DynamicallyLoaded;"); | ||||
|                               expect(tc.nativeElement).toHaveText("Location;DynamicallyLoaded;"); | ||||
|                               async.done(); | ||||
|                             }); | ||||
|                       }); | ||||
| @ -60,7 +60,7 @@ export function main() { | ||||
|                         loader.loadIntoLocation(DynamicallyLoaded, tc.elementRef, 'loc') | ||||
|                             .then(ref => { | ||||
|                               ref.dispose(); | ||||
|                               expect(tc.domElement).toHaveText("Location;"); | ||||
|                               expect(tc.nativeElement).toHaveText("Location;"); | ||||
|                               async.done(); | ||||
|                             }); | ||||
|                       }); | ||||
| @ -81,7 +81,7 @@ export function main() { | ||||
| 
 | ||||
|                            tc.detectChanges(); | ||||
| 
 | ||||
|                            var newlyInsertedElement = DOM.childNodes(tc.domElement)[1]; | ||||
|                            var newlyInsertedElement = DOM.childNodes(tc.nativeElement)[1]; | ||||
|                            expect(newlyInsertedElement.id) | ||||
|                                .toEqual("new value") | ||||
| 
 | ||||
|  | ||||
| @ -256,8 +256,8 @@ export function main() { | ||||
| 
 | ||||
|                  view.detectChanges(); | ||||
| 
 | ||||
|                  expect(q.query.first.domElement).toHaveText("1d"); | ||||
|                  expect(q.query.last.domElement).toHaveText("2d"); | ||||
|                  expect(q.query.first.nativeElement).toHaveText("1d"); | ||||
|                  expect(q.query.last.nativeElement).toHaveText("2d"); | ||||
| 
 | ||||
|                  async.done(); | ||||
|                }); | ||||
|  | ||||
| @ -16,14 +16,12 @@ import { | ||||
|   proxy | ||||
| } from 'angular2/test_lib'; | ||||
| 
 | ||||
| import {MapWrapper} from 'angular2/src/facade/collection'; | ||||
| import {IMPLEMENTS} from 'angular2/src/facade/lang'; | ||||
| 
 | ||||
| import {AppView, AppProtoView, AppViewContainer} from 'angular2/src/core/compiler/view'; | ||||
| import {ProtoViewRef, ViewRef, internalView} from 'angular2/src/core/compiler/view_ref'; | ||||
| import {ElementRef} from 'angular2/src/core/compiler/element_ref'; | ||||
| import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref'; | ||||
| import {AppViewManager} from 'angular2/src/core/compiler/view_manager'; | ||||
| import {ElementBinder} from 'angular2/src/core/compiler/element_binder'; | ||||
| 
 | ||||
| export function main() { | ||||
|   // TODO(tbosch): add missing tests
 | ||||
| @ -33,9 +31,11 @@ export function main() { | ||||
|     var view; | ||||
|     var viewManager; | ||||
| 
 | ||||
|     function wrapView(view: AppView): ViewRef { return new ViewRef(view); } | ||||
| 
 | ||||
|     function createProtoView() { return new AppProtoView(null, null, null, null); } | ||||
|     function createProtoView() { | ||||
|       var pv = new AppProtoView(null, null, null, null); | ||||
|       pv.elementBinders = [new ElementBinder(0, null, 0, null, null)]; | ||||
|       return pv; | ||||
|     } | ||||
| 
 | ||||
|     function createView() { return new AppView(null, createProtoView(), new Map()); } | ||||
| 
 | ||||
| @ -45,7 +45,7 @@ export function main() { | ||||
|       viewManager = new AppViewManagerSpy(); | ||||
|       view = createView(); | ||||
|       view.viewContainers = [null]; | ||||
|       location = new ElementRef(wrapView(view), 0); | ||||
|       location = view.elementRefs[0]; | ||||
|     }); | ||||
| 
 | ||||
|     describe('length', () => { | ||||
|  | ||||
| @ -21,7 +21,6 @@ import {MapWrapper, ListWrapper, StringMapWrapper} from 'angular2/src/facade/col | ||||
| 
 | ||||
| import {AppProtoView, AppView, AppViewContainer} from 'angular2/src/core/compiler/view'; | ||||
| import {ProtoViewRef, ViewRef, internalView} from 'angular2/src/core/compiler/view_ref'; | ||||
| import {ElementRef} from 'angular2/src/core/compiler/element_ref'; | ||||
| import {Renderer, RenderViewRef, RenderProtoViewRef} from 'angular2/src/render/api'; | ||||
| import {ElementBinder} from 'angular2/src/core/compiler/element_binder'; | ||||
| import {DirectiveBinding, ElementInjector} from 'angular2/src/core/compiler/element_injector'; | ||||
| @ -50,7 +49,7 @@ export function main() { | ||||
|     function wrapView(view: AppView): ViewRef { return new ViewRef(view); } | ||||
| 
 | ||||
|     function elementRef(parentView, boundElementIndex) { | ||||
|       return new ElementRef(parentView, boundElementIndex); | ||||
|       return parentView.elementRefs[boundElementIndex]; | ||||
|     } | ||||
| 
 | ||||
|     function createDirectiveBinding(type) { | ||||
| @ -277,13 +276,12 @@ export function main() { | ||||
|         }); | ||||
| 
 | ||||
|         it('should create a ViewContainerRef if not yet existing', () => { | ||||
|           manager.createViewInContainer(elementRef(wrapView(parentView), 0), 0, | ||||
|                                         wrapPv(childProtoView), null); | ||||
|           manager.createViewInContainer(elementRef(parentView, 0), 0, wrapPv(childProtoView), null); | ||||
|           expect(parentView.viewContainers[0]).toBeTruthy(); | ||||
|         }); | ||||
| 
 | ||||
|         it('should create the view', () => { | ||||
|           expect(internalView(manager.createViewInContainer(elementRef(wrapView(parentView), 0), 0, | ||||
|           expect(internalView(manager.createViewInContainer(elementRef(parentView, 0), 0, | ||||
|                                                             wrapPv(childProtoView), null))) | ||||
|               .toBe(createdViews[0]); | ||||
|           expect(createdViews[0].proto).toBe(childProtoView); | ||||
| @ -291,10 +289,11 @@ export function main() { | ||||
|         }); | ||||
| 
 | ||||
|         it('should attach the view', () => { | ||||
|           var contextView = createView(); | ||||
|           var elRef = elementRef(wrapView(parentView), 0); | ||||
|           var contextView = | ||||
|               createView(createProtoView([createEmptyElBinder(), createEmptyElBinder()])); | ||||
|           var elRef = elementRef(parentView, 0); | ||||
|           manager.createViewInContainer(elRef, 0, wrapPv(childProtoView), | ||||
|                                         elementRef(wrapView(contextView), 1), null); | ||||
|                                         elementRef(contextView, 1), null); | ||||
|           expect(utils.spy('attachViewInContainer')) | ||||
|               .toHaveBeenCalledWith(parentView, 0, contextView, 1, 0, createdViews[0]); | ||||
|           expect(renderer.spy('attachViewInContainer')) | ||||
| @ -303,25 +302,25 @@ export function main() { | ||||
| 
 | ||||
|         it('should hydrate the view', () => { | ||||
|           var injector = new Injector([], null, false); | ||||
|           var contextView = createView(); | ||||
|           manager.createViewInContainer(elementRef(wrapView(parentView), 0), 0, | ||||
|                                         wrapPv(childProtoView), | ||||
|                                         elementRef(wrapView(contextView), 1), injector); | ||||
|           var contextView = | ||||
|               createView(createProtoView([createEmptyElBinder(), createEmptyElBinder()])); | ||||
|           manager.createViewInContainer(elementRef(parentView, 0), 0, wrapPv(childProtoView), | ||||
|                                         elementRef(contextView, 1), injector); | ||||
|           expect(utils.spy('hydrateViewInContainer')) | ||||
|               .toHaveBeenCalledWith(parentView, 0, contextView, 1, 0, injector); | ||||
|           expect(renderer.spy('hydrateView')).toHaveBeenCalledWith(createdViews[0].render); | ||||
|         }); | ||||
| 
 | ||||
|         it('should create and set the render view', () => { | ||||
|           manager.createViewInContainer(elementRef(wrapView(parentView), 0), 0, | ||||
|                                         wrapPv(childProtoView), null, null); | ||||
|           manager.createViewInContainer(elementRef(parentView, 0), 0, wrapPv(childProtoView), null, | ||||
|                                         null); | ||||
|           expect(renderer.spy('createView')).toHaveBeenCalledWith(childProtoView.render); | ||||
|           expect(createdViews[0].render).toBe(createdRenderViews[0]); | ||||
|         }); | ||||
| 
 | ||||
|         it('should set the event dispatcher', () => { | ||||
|           manager.createViewInContainer(elementRef(wrapView(parentView), 0), 0, | ||||
|                                         wrapPv(childProtoView), null, null); | ||||
|           manager.createViewInContainer(elementRef(parentView, 0), 0, wrapPv(childProtoView), null, | ||||
|                                         null); | ||||
|           var childView = createdViews[0]; | ||||
|           expect(renderer.spy('setEventDispatcher')) | ||||
|               .toHaveBeenCalledWith(childView.render, childView); | ||||
| @ -337,19 +336,19 @@ export function main() { | ||||
|         beforeEach(() => { | ||||
|           parentView = createView(createProtoView([createEmptyElBinder()])); | ||||
|           childProtoView = createProtoView(); | ||||
|           childView = internalView(manager.createViewInContainer( | ||||
|               elementRef(wrapView(parentView), 0), 0, wrapPv(childProtoView), null)); | ||||
|           childView = internalView(manager.createViewInContainer(elementRef(parentView, 0), 0, | ||||
|                                                                  wrapPv(childProtoView), null)); | ||||
|         }); | ||||
| 
 | ||||
|         it('should dehydrate', () => { | ||||
|           manager.destroyViewInContainer(elementRef(wrapView(parentView), 0), 0); | ||||
|           manager.destroyViewInContainer(elementRef(parentView, 0), 0); | ||||
|           expect(utils.spy('dehydrateView')) | ||||
|               .toHaveBeenCalledWith(parentView.viewContainers[0].views[0]); | ||||
|           expect(renderer.spy('dehydrateView')).toHaveBeenCalledWith(childView.render); | ||||
|         }); | ||||
| 
 | ||||
|         it('should detach', () => { | ||||
|           var elRef = elementRef(wrapView(parentView), 0); | ||||
|           var elRef = elementRef(parentView, 0); | ||||
|           manager.destroyViewInContainer(elRef, 0); | ||||
|           expect(utils.spy('detachViewInContainer')).toHaveBeenCalledWith(parentView, 0, 0); | ||||
|           expect(renderer.spy('detachViewInContainer')) | ||||
| @ -357,7 +356,7 @@ export function main() { | ||||
|         }); | ||||
| 
 | ||||
|         it('should return the view to the pool', () => { | ||||
|           manager.destroyViewInContainer(elementRef(wrapView(parentView), 0), 0); | ||||
|           manager.destroyViewInContainer(elementRef(parentView, 0), 0); | ||||
|           expect(viewPool.spy('returnView')).toHaveBeenCalledWith(childView); | ||||
|         }); | ||||
|       }); | ||||
| @ -367,8 +366,8 @@ export function main() { | ||||
|         beforeEach(() => { | ||||
|           parentView = createView(createProtoView([createEmptyElBinder()])); | ||||
|           childProtoView = createProtoView(); | ||||
|           childView = internalView(manager.createViewInContainer( | ||||
|               elementRef(wrapView(parentView), 0), 0, wrapPv(childProtoView), null)); | ||||
|           childView = internalView(manager.createViewInContainer(elementRef(parentView, 0), 0, | ||||
|                                                                  wrapPv(childProtoView), null)); | ||||
|         }); | ||||
| 
 | ||||
|         it('should dehydrate', () => { | ||||
|  | ||||
| @ -142,25 +142,26 @@ export function main() { | ||||
|                var rootCompChildren = rootTestComponent.componentViewChildren; | ||||
|                // The root component has 3 elements in its shadow view.
 | ||||
|                expect(rootCompChildren.length).toEqual(3); | ||||
|                expect(DOM.hasClass(rootCompChildren[0].domElement, 'parent')).toBe(true); | ||||
|                expect(DOM.hasClass(rootCompChildren[1].domElement, 'parent')).toBe(true); | ||||
|                expect(DOM.hasClass(rootCompChildren[2].domElement, 'child-comp-class')).toBe(true); | ||||
|                expect(DOM.hasClass(rootCompChildren[0].nativeElement, 'parent')).toBe(true); | ||||
|                expect(DOM.hasClass(rootCompChildren[1].nativeElement, 'parent')).toBe(true); | ||||
|                expect(DOM.hasClass(rootCompChildren[2].nativeElement, 'child-comp-class')) | ||||
|                    .toBe(true); | ||||
| 
 | ||||
|                var nested = rootCompChildren[0].children; | ||||
|                expect(nested.length).toEqual(1); | ||||
|                expect(DOM.hasClass(nested[0].domElement, 'parentnested')).toBe(true); | ||||
|                expect(DOM.hasClass(nested[0].nativeElement, 'parentnested')).toBe(true); | ||||
| 
 | ||||
|                var childComponent = rootCompChildren[2]; | ||||
|                expect(childComponent.children.length).toEqual(0); | ||||
| 
 | ||||
|                var childCompChildren = childComponent.componentViewChildren; | ||||
|                expect(childCompChildren.length).toEqual(2); | ||||
|                expect(DOM.hasClass(childCompChildren[0].domElement, 'child')).toBe(true); | ||||
|                expect(DOM.hasClass(childCompChildren[1].domElement, 'child')).toBe(true); | ||||
|                expect(DOM.hasClass(childCompChildren[0].nativeElement, 'child')).toBe(true); | ||||
|                expect(DOM.hasClass(childCompChildren[1].nativeElement, 'child')).toBe(true); | ||||
| 
 | ||||
|                var childNested = childCompChildren[0].children; | ||||
|                expect(childNested.length).toEqual(1); | ||||
|                expect(DOM.hasClass(childNested[0].domElement, 'childnested')).toBe(true); | ||||
|                expect(DOM.hasClass(childNested[0].nativeElement, 'childnested')).toBe(true); | ||||
| 
 | ||||
|                async.done(); | ||||
|              }); | ||||
| @ -193,10 +194,10 @@ export function main() { | ||||
|                var childTestEls = rootTestComponent.queryAll(By.directive(MessageDir)); | ||||
| 
 | ||||
|                expect(childTestEls.length).toBe(4); | ||||
|                expect(DOM.hasClass(childTestEls[0].domElement, 'parent')).toBe(true); | ||||
|                expect(DOM.hasClass(childTestEls[1].domElement, 'parentnested')).toBe(true); | ||||
|                expect(DOM.hasClass(childTestEls[2].domElement, 'child')).toBe(true); | ||||
|                expect(DOM.hasClass(childTestEls[3].domElement, 'childnested')).toBe(true); | ||||
|                expect(DOM.hasClass(childTestEls[0].nativeElement, 'parent')).toBe(true); | ||||
|                expect(DOM.hasClass(childTestEls[1].nativeElement, 'parentnested')).toBe(true); | ||||
|                expect(DOM.hasClass(childTestEls[2].nativeElement, 'child')).toBe(true); | ||||
|                expect(DOM.hasClass(childTestEls[3].nativeElement, 'childnested')).toBe(true); | ||||
|                async.done(); | ||||
|              }); | ||||
|        })); | ||||
| @ -213,7 +214,7 @@ export function main() { | ||||
|                var childTestEls = parentEl.queryAll(By.directive(MessageDir), Scope.light); | ||||
| 
 | ||||
|                expect(childTestEls.length).toBe(1); | ||||
|                expect(DOM.hasClass(childTestEls[0].domElement, 'parentnested')).toBe(true); | ||||
|                expect(DOM.hasClass(childTestEls[0].nativeElement, 'parentnested')).toBe(true); | ||||
| 
 | ||||
|                async.done(); | ||||
|              }); | ||||
| @ -229,8 +230,8 @@ export function main() { | ||||
|                var childTestEls = rootTestComponent.queryAll(By.directive(MessageDir), Scope.view); | ||||
| 
 | ||||
|                expect(childTestEls.length).toBe(2); | ||||
|                expect(DOM.hasClass(childTestEls[0].domElement, 'parent')).toBe(true); | ||||
|                expect(DOM.hasClass(childTestEls[1].domElement, 'parentnested')).toBe(true); | ||||
|                expect(DOM.hasClass(childTestEls[0].nativeElement, 'parent')).toBe(true); | ||||
|                expect(DOM.hasClass(childTestEls[1].nativeElement, 'parentnested')).toBe(true); | ||||
| 
 | ||||
|                async.done(); | ||||
|              }); | ||||
|  | ||||
| @ -15,7 +15,7 @@ import { | ||||
|   TestComponentBuilder, | ||||
|   By, | ||||
|   Scope, | ||||
|   inspectDomElement | ||||
|   inspectNativeElement | ||||
| } from 'angular2/test_lib'; | ||||
| 
 | ||||
| import {global} from 'angular2/src/facade/lang'; | ||||
| @ -45,7 +45,7 @@ export function main() { | ||||
|          tcb.overrideTemplate(MyComp, '<div some-dir></div>') | ||||
|              .createAsync(MyComp) | ||||
|              .then((rootTestComponent) => { | ||||
|                expect(inspectDomElement(rootTestComponent.domElement).componentInstance) | ||||
|                expect(inspectNativeElement(rootTestComponent.nativeElement).componentInstance) | ||||
|                    .toBeAnInstanceOf(MyComp); | ||||
| 
 | ||||
|                async.done(); | ||||
| @ -58,7 +58,7 @@ export function main() { | ||||
|              .createAsync(MyComp) | ||||
|              .then((rootTestComponent) => { | ||||
|                rootTestComponent.destroy(); | ||||
|                expect(inspectDomElement(rootTestComponent.domElement)).toBe(null); | ||||
|                expect(inspectNativeElement(rootTestComponent.nativeElement)).toBe(null); | ||||
| 
 | ||||
|                async.done(); | ||||
|              }); | ||||
| @ -71,7 +71,7 @@ export function main() { | ||||
|            tcb.overrideTemplate(MyComp, '') | ||||
|                .createAsync(MyComp) | ||||
|                .then((rootTestComponent) => { | ||||
|                  expect(global['ngProbe'](rootTestComponent.domElement).componentInstance) | ||||
|                  expect(global['ngProbe'](rootTestComponent.nativeElement).componentInstance) | ||||
|                      .toBeAnInstanceOf(MyComp); | ||||
| 
 | ||||
|                  async.done(); | ||||
|  | ||||
| @ -61,7 +61,7 @@ export function main() { | ||||
| 
 | ||||
| @Directive({selector: '[test-dec]'}) | ||||
| class TestDirective { | ||||
|   constructor(el: ElementRef) { DOM.addClass(el.domElement, 'compiled'); } | ||||
|   constructor(el: ElementRef) { DOM.addClass(el.nativeElement, 'compiled'); } | ||||
| } | ||||
| 
 | ||||
| @Component({selector: 'test-cmp'}) | ||||
|  | ||||
| @ -46,7 +46,7 @@ export function main() { | ||||
|        inject([AsyncTestCompleter], (async) => { | ||||
|          var ruler = new Ruler(DOM); | ||||
|          var elRef = <any>new SpyElementRef(); | ||||
|          elRef.domElement = DOM.createElement('div'); | ||||
|          elRef.nativeElement = DOM.createElement('div'); | ||||
|          ruler.measure(elRef).then((rect) => { | ||||
|            // here we are using an element created in a doc fragment so all the measures will come
 | ||||
|            // back as 0
 | ||||
| @ -61,7 +61,7 @@ export function main() { | ||||
| @proxy | ||||
| @IMPLEMENTS(ElementRef) | ||||
| class SpyElementRef extends SpyObject { | ||||
|   domElement; | ||||
|   nativeElement; | ||||
|   constructor() { super(ElementRef); } | ||||
|   noSuchMethod(m) { return super.noSuchMethod(m) } | ||||
| } | ||||
|  | ||||
| @ -62,7 +62,7 @@ export function main() { | ||||
|          tcb.createAsync(ChildComp).then((rootTestComponent) => { | ||||
|            rootTestComponent.detectChanges(); | ||||
| 
 | ||||
|            expect(rootTestComponent.domElement).toHaveText('Original Child'); | ||||
|            expect(rootTestComponent.nativeElement).toHaveText('Original Child'); | ||||
|            async.done(); | ||||
|          }); | ||||
|        })); | ||||
| @ -72,11 +72,11 @@ export function main() { | ||||
| 
 | ||||
|          tcb.createAsync(MyIfComp).then((rootTestComponent) => { | ||||
|            rootTestComponent.detectChanges(); | ||||
|            expect(rootTestComponent.domElement).toHaveText('MyIf()'); | ||||
|            expect(rootTestComponent.nativeElement).toHaveText('MyIf()'); | ||||
| 
 | ||||
|            rootTestComponent.componentInstance.showMore = true; | ||||
|            rootTestComponent.detectChanges(); | ||||
|            expect(rootTestComponent.domElement).toHaveText('MyIf(More)'); | ||||
|            expect(rootTestComponent.nativeElement).toHaveText('MyIf(More)'); | ||||
| 
 | ||||
|            async.done(); | ||||
|          }); | ||||
| @ -89,7 +89,7 @@ export function main() { | ||||
|              .createAsync(MockChildComp) | ||||
|              .then((rootTestComponent) => { | ||||
|                rootTestComponent.detectChanges(); | ||||
|                expect(rootTestComponent.domElement).toHaveText('Mock'); | ||||
|                expect(rootTestComponent.nativeElement).toHaveText('Mock'); | ||||
| 
 | ||||
|                async.done(); | ||||
|              }); | ||||
| @ -103,7 +103,7 @@ export function main() { | ||||
|              .createAsync(ChildComp) | ||||
|              .then((rootTestComponent) => { | ||||
|                rootTestComponent.detectChanges(); | ||||
|                expect(rootTestComponent.domElement).toHaveText('Modified Child'); | ||||
|                expect(rootTestComponent.nativeElement).toHaveText('Modified Child'); | ||||
| 
 | ||||
|                async.done(); | ||||
|              }); | ||||
| @ -116,7 +116,7 @@ export function main() { | ||||
|              .createAsync(ParentComp) | ||||
|              .then((rootTestComponent) => { | ||||
|                rootTestComponent.detectChanges(); | ||||
|                expect(rootTestComponent.domElement).toHaveText('Parent(Mock)'); | ||||
|                expect(rootTestComponent.nativeElement).toHaveText('Parent(Mock)'); | ||||
| 
 | ||||
|                async.done(); | ||||
|              }); | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| import {ElementRef, Component, Directive, View, Injectable} from 'angular2/angular2'; | ||||
| import {ElementRef, Component, Directive, View, Injectable, Renderer} from 'angular2/angular2'; | ||||
| 
 | ||||
| // A service available to the Injector, used by the HelloCmp component.
 | ||||
| @Injectable() | ||||
| @ -12,7 +12,7 @@ class GreetingService { | ||||
| class RedDec { | ||||
|   // ElementRef is always injectable and it wraps the element on which the
 | ||||
|   // directive was found by the compiler.
 | ||||
|   constructor(el: ElementRef) { el.domElement.style.color = 'red'; } | ||||
|   constructor(el: ElementRef, renderer: Renderer) { renderer.setElementStyle(el, 'color', 'red'); } | ||||
| } | ||||
| 
 | ||||
| // Angular 2.0 supports 2 basic types of directives:
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user