refactor(compiler): remove Viewport directives, use Decorator instead

BREAKING_CHANGE:
- The special type of `Viewport` directives is removed
  in favor of a more general `Decorator` directive
- `ViewContainerRef` now no more has a default `ProtoViewRef`
  but requires an explicit one when creating views.

Closes #1536
This commit is contained in:
Tobias Bosch
2015-04-29 15:07:55 -07:00
parent fb67e37339
commit 3aac2fefd7
35 changed files with 280 additions and 366 deletions
+4 -16
View File
@@ -21,7 +21,7 @@ import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
import {AppProtoView} from 'angular2/src/core/compiler/view';
import {ElementBinder} from 'angular2/src/core/compiler/element_binder';
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
import {Component, DynamicComponent, Viewport, Decorator} from 'angular2/src/core/annotations_impl/annotations';
import {Component, DynamicComponent, Decorator} from 'angular2/src/core/annotations_impl/annotations';
import {Attribute} from 'angular2/src/core/annotations_impl/di';
import {View} from 'angular2/src/core/annotations_impl/view';
import {internalProtoView} from 'angular2/src/core/compiler/view_ref';
@@ -150,13 +150,6 @@ export function main() {
});
}));
it('should fill directive.type for viewport directives', inject([AsyncTestCompleter], (async) => {
captureDirective(SomeViewportDirective).then( (renderDir) => {
expect(renderDir.type).toEqual(renderApi.DirectiveMetadata.VIEWPORT_TYPE);
async.done();
});
}));
it('should fill directive.type for decorator directives', inject([AsyncTestCompleter], (async) => {
captureDirective(SomeDecoratorDirective).then( (renderDir) => {
expect(renderDir.type).toEqual(renderApi.DirectiveMetadata.DECORATOR_TYPE);
@@ -297,7 +290,7 @@ export function main() {
});
}));
it('should load nested components in viewport', inject([AsyncTestCompleter], (async) => {
it('should load nested components in viewcontainers', inject([AsyncTestCompleter], (async) => {
tplResolver.setView(MainComponent, new View({template: '<div></div>'}));
tplResolver.setView(NestedComponent, new View({template: '<div></div>'}));
var mainProtoView = createProtoView([
@@ -451,16 +444,14 @@ function createComponentElementBinder(reader, type) {
var binding = createDirectiveBinding(reader, type);
return new ElementBinder(
0, null, 0,
null, binding,
null
null, binding
);
}
function createViewportElementBinder(nestedProtoView) {
var elBinder = new ElementBinder(
0, null, 0,
null, null,
null
null, null
);
elBinder.nestedProtoView = nestedProtoView;
return elBinder;
@@ -502,9 +493,6 @@ class RecursiveComponent {}
@DynamicComponent()
class SomeDynamicComponentDirective {}
@Viewport()
class SomeViewportDirective {}
@Decorator()
class SomeDecoratorDirective {}
@@ -2,7 +2,7 @@ import {isPresent} from 'angular2/src/facade/lang';
import {ListWrapper} from 'angular2/src/facade/collection';
import {ddescribe, describe, it, iit, expect, beforeEach} from 'angular2/test_lib';
import {DirectiveMetadataReader} from 'angular2/src/core/compiler/directive_metadata_reader';
import {Decorator, Component, Viewport} from 'angular2/src/core/annotations_impl/annotations';
import {Decorator, Component} from 'angular2/src/core/annotations_impl/annotations';
import {DirectiveMetadata} from 'angular2/src/core/compiler/directive_metadata';
import {Injectable, Injector} from 'angular2/di';
@@ -15,9 +15,6 @@ class SomeDecorator {}
@Component({selector: 'someComponent', injectables: [SomeInjectable]})
class SomeComponent {}
@Viewport({selector: 'someViewport'})
class SomeViewport {}
class SomeDirectiveWithoutAnnotation {
}
@@ -35,12 +32,6 @@ export function main() {
new DirectiveMetadata(SomeDecorator, new Decorator({selector: 'someDecorator'}), null));
});
it('should read out the Viewport annotation', () => {
var directiveMetadata = reader.read(SomeViewport);
expect(directiveMetadata).toEqual(
new DirectiveMetadata(SomeViewport, new Viewport({selector: 'someViewport'}), null));
});
it('should read out the Component annotation', () => {
var m = reader.read(SomeComponent);
// For some reason `toEqual` fails to compare ResolvedBinding objects.
@@ -16,7 +16,7 @@ import {
import {TestBed} from 'angular2/src/test_lib/test_bed';
import {Decorator, Component, Viewport, DynamicComponent} from 'angular2/src/core/annotations_impl/annotations';
import {Decorator, Component, DynamicComponent} from 'angular2/src/core/annotations_impl/annotations';
import {View} from 'angular2/src/core/annotations_impl/view';
import {DynamicComponentLoader} from 'angular2/src/core/compiler/dynamic_component_loader';
import {ElementRef} from 'angular2/src/core/compiler/element_ref';
@@ -61,7 +61,7 @@ export function main() {
});
}));
it('should allow to destroy and create them via viewport directives',
it('should allow to destroy and create them via viewcontainer directives',
inject([TestBed, AsyncTestCompleter], (tb, async) => {
tb.overrideView(MyComp, new View({
template: '<div><dynamic-comp #dynamic template="if: ctxBoolProp"></dynamic-comp></div>',
@@ -705,6 +705,12 @@ export function main() {
expect(inj.get(NeedsProtoViewRef).protoViewRef).toEqual(new ProtoViewRef(protoView));
});
it("should throw if there is no ProtoViewRef", function () {
expect(
() => injector([NeedsProtoViewRef])
).toThrowError('No provider for ProtoViewRef! (NeedsProtoViewRef -> ProtoViewRef)');
});
});
describe('directive queries', () => {
+8 -7
View File
@@ -24,7 +24,7 @@ import {Injector, bind} from 'angular2/di';
import {PipeRegistry, defaultPipeRegistry,
ChangeDetection, DynamicChangeDetection, Pipe, ChangeDetectorRef, ON_PUSH} from 'angular2/change_detection';
import {Decorator, Component, Viewport, DynamicComponent} from 'angular2/src/core/annotations_impl/annotations';
import {Decorator, Component, DynamicComponent} from 'angular2/src/core/annotations_impl/annotations';
import {View} from 'angular2/src/core/annotations_impl/view';
import {Parent, Ancestor} from 'angular2/src/core/annotations_impl/visibility';
import {Attribute} from 'angular2/src/core/annotations_impl/di';
@@ -32,6 +32,7 @@ import {Attribute} from 'angular2/src/core/annotations_impl/di';
import {If} from 'angular2/src/directives/if';
import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref';
import {ProtoViewRef} from 'angular2/src/core/compiler/view_ref';
import {Compiler} from 'angular2/src/core/compiler/compiler';
import {ElementRef} from 'angular2/src/core/compiler/element_ref';
@@ -522,7 +523,7 @@ export function main() {
})
}));
it('should create a component that injects an @Ancestor through viewport directive', inject([TestBed, AsyncTestCompleter], (tb, async) => {
it('should create a component that injects an @Ancestor through viewcontainer directive', inject([TestBed, AsyncTestCompleter], (tb, async) => {
tb.overrideView(MyComp, new View({
template: `
<some-directive>
@@ -865,7 +866,7 @@ class DynamicViewport {
var myService = new MyService();
myService.greeting = 'dynamic greet';
this.done = compiler.compileInHost(ChildCompUsingService).then( (hostPv) => {
vc.create(0, hostPv, inj.createChildFromResolved(Injector.resolve([bind(MyService).toValue(myService)])))
vc.create(hostPv, 0, inj.createChildFromResolved(Injector.resolve([bind(MyService).toValue(myService)])))
});
}
}
@@ -1037,13 +1038,13 @@ class ChildComp2 {
}
}
@Viewport({
@Decorator({
selector: '[some-viewport]'
})
class SomeViewport {
constructor(container: ViewContainerRef) {
container.create().setLocal('some-tmpl', 'hello');
container.create().setLocal('some-tmpl', 'again');
constructor(container: ViewContainerRef, protoView:ProtoViewRef) {
container.create(protoView).setLocal('some-tmpl', 'hello');
container.create(protoView).setLocal('some-tmpl', 'again');
}
}
@@ -44,8 +44,8 @@ export function main() {
return new AppView(null, createProtoView(), MapWrapper.create());
}
function createViewContainer(defaultProtoView = null) {
return new ViewContainerRef(viewManager, location, defaultProtoView);
function createViewContainer() {
return new ViewContainerRef(viewManager, location);
}
beforeEach( () => {
+2 -2
View File
@@ -60,12 +60,12 @@ export function main() {
}
function createEmptyElBinder() {
return new ElementBinder(0, null, 0, null, null, null);
return new ElementBinder(0, null, 0, null, null);
}
function createComponentElBinder(nestedProtoView = null) {
var binding = createDirectiveBinding(SomeComponent);
var binder = new ElementBinder(0, null, 0, null, binding, null);
var binder = new ElementBinder(0, null, 0, null, binding);
binder.nestedProtoView = nestedProtoView;
return binder;
}
@@ -45,12 +45,12 @@ export function main() {
}
function createEmptyElBinder() {
return new ElementBinder(0, null, 0, null, null, null);
return new ElementBinder(0, null, 0, null, null);
}
function createComponentElBinder(nestedProtoView = null) {
var binding = createDirectiveBinding(SomeComponent);
var binder = new ElementBinder(0, null, 0, null, binding, null);
var binder = new ElementBinder(0, null, 0, null, binding);
binder.nestedProtoView = nestedProtoView;
return binder;
}