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:
+4
-16
@@ -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
@@ -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( () => {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -17,8 +17,6 @@ export function main() {
|
||||
annotatedDirectives = [
|
||||
someComponent,
|
||||
someComponent2,
|
||||
someViewport,
|
||||
someViewport2,
|
||||
someDecorator,
|
||||
someDecoratorIgnoringChildren,
|
||||
decoratorWithMultipleAttrs,
|
||||
@@ -153,27 +151,6 @@ export function main() {
|
||||
expect(eventBinding.source.source).toEqual('doItGlobal()');
|
||||
});
|
||||
|
||||
//TODO: assertions should be enabled when running tests: https://github.com/angular/angular/issues/1340
|
||||
describe('viewport directives', () => {
|
||||
it('should not allow multiple viewport directives on the same element', () => {
|
||||
expect( () => {
|
||||
process(
|
||||
el('<template some-vp some-vp2></template>')
|
||||
);
|
||||
}).toThrowError('Only one viewport directive is allowed per element - check '
|
||||
+ (assertionsEnabled() ? '<template some-vp some-vp2>' : 'null'));
|
||||
});
|
||||
|
||||
it('should not allow viewport directives on non <template> elements', () => {
|
||||
expect( () => {
|
||||
process(
|
||||
el('<div some-vp></div>')
|
||||
);
|
||||
}).toThrowError('Viewport directives need to be placed on <template> elements or elements with template attribute - check '
|
||||
+ (assertionsEnabled() ? '<div some-vp>' : 'null'));
|
||||
});
|
||||
});
|
||||
|
||||
//TODO: assertions should be enabled when running tests: https://github.com/angular/angular/issues/1340
|
||||
describe('component directives', () => {
|
||||
it('should save the component id', () => {
|
||||
@@ -231,18 +208,6 @@ var someComponent2 = new DirectiveMetadata({
|
||||
type: DirectiveMetadata.COMPONENT_TYPE
|
||||
});
|
||||
|
||||
var someViewport = new DirectiveMetadata({
|
||||
selector: '[some-vp]',
|
||||
id: 'someViewport',
|
||||
type: DirectiveMetadata.VIEWPORT_TYPE
|
||||
});
|
||||
|
||||
var someViewport2 = new DirectiveMetadata({
|
||||
selector: '[some-vp2]',
|
||||
id: 'someViewport2',
|
||||
type: DirectiveMetadata.VIEWPORT_TYPE
|
||||
});
|
||||
|
||||
var someDecorator = new DirectiveMetadata({
|
||||
selector: '[some-decor]',
|
||||
type: DirectiveMetadata.DECORATOR_TYPE
|
||||
|
||||
+2
-2
@@ -43,7 +43,7 @@ export function main() {
|
||||
['properties', MapWrapper.createFromPairs([['propKey', 'propVal']])],
|
||||
['readAttributes', ['readTest1', 'readTest2']],
|
||||
['selector', 'testSelector'],
|
||||
['type', DirectiveMetadata.VIEWPORT_TYPE]
|
||||
['type', DirectiveMetadata.DECORATOR_TYPE]
|
||||
]);
|
||||
var meta = directiveMetadataFromMap(map);
|
||||
expect(meta.compileChildren).toEqual(false);
|
||||
@@ -56,7 +56,7 @@ export function main() {
|
||||
MapWrapper.createFromPairs([['propKey', 'propVal']]));
|
||||
expect(meta.readAttributes).toEqual(['readTest1', 'readTest2']);
|
||||
expect(meta.selector).toEqual('testSelector');
|
||||
expect(meta.type).toEqual(DirectiveMetadata.VIEWPORT_TYPE);
|
||||
expect(meta.type).toEqual(DirectiveMetadata.DECORATOR_TYPE);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -405,7 +405,7 @@ var multipleContentTagsComponent = new DirectiveMetadata({
|
||||
var manualViewportDirective = new DirectiveMetadata({
|
||||
selector: '[manual]',
|
||||
id: 'manual',
|
||||
type: DirectiveMetadata.VIEWPORT_TYPE
|
||||
type: DirectiveMetadata.DECORATOR_TYPE
|
||||
});
|
||||
|
||||
var outerWithIndirectNestedComponent = new DirectiveMetadata({
|
||||
@@ -441,7 +441,7 @@ var conditionalContentComponent = new DirectiveMetadata({
|
||||
var autoViewportDirective = new DirectiveMetadata({
|
||||
selector: '[auto]',
|
||||
id: '[auto]',
|
||||
type: DirectiveMetadata.VIEWPORT_TYPE
|
||||
type: DirectiveMetadata.DECORATOR_TYPE
|
||||
});
|
||||
|
||||
var tabGroupComponent = new DirectiveMetadata({
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ import {
|
||||
import {TestBed} from 'angular2/test';
|
||||
|
||||
import {Injector, bind} from 'angular2/di';
|
||||
import {Component, Viewport} from 'angular2/src/core/annotations_impl/annotations';
|
||||
import {Component} from 'angular2/src/core/annotations_impl/annotations';
|
||||
import {View} from 'angular2/src/core/annotations_impl/view';
|
||||
|
||||
import {RootRouter} from 'angular2/src/router/router';
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ import {
|
||||
import {IMPLEMENTS} from 'angular2/src/facade/lang';
|
||||
|
||||
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
||||
import {RootRouter, Viewport} from 'angular2/src/router/router';
|
||||
import {RootRouter} from 'angular2/src/router/router';
|
||||
import {Pipeline} from 'angular2/src/router/pipeline';
|
||||
import {RouterOutlet} from 'angular2/src/router/router_outlet';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user