feat(di): removed publishAs
BREAKING CHANGES Removes the publishAs property from the Component annotation.
This commit is contained in:
parent
155b1e2b35
commit
3a53f67911
@ -845,41 +845,6 @@ export class Component extends Directive {
|
|||||||
*/
|
*/
|
||||||
injectables:List;
|
injectables:List;
|
||||||
|
|
||||||
// TODO(naomib): needs documentation
|
|
||||||
/**
|
|
||||||
* Dependency injection tokens that this component publishes _itself_ to its
|
|
||||||
* children in its view via the application injector.
|
|
||||||
*
|
|
||||||
* ## Examples
|
|
||||||
*
|
|
||||||
* Imagine you have parent component that implements the [RpcService]
|
|
||||||
* interface. It can pose as [RpcService] to its children. Child components
|
|
||||||
* do not need to know about this fact. They only need to declare their
|
|
||||||
* dependency on [RpcService] without knowing exactly how it is provided.
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* @Component({
|
|
||||||
* selector: 'parent',
|
|
||||||
* publishAs: [RpcService]
|
|
||||||
* })
|
|
||||||
* @View({
|
|
||||||
* template: '<child></child>',
|
|
||||||
* directives: [Child]
|
|
||||||
* })
|
|
||||||
* class Parent implements RpcService {
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* @Component({
|
|
||||||
* selector: 'child'
|
|
||||||
* })
|
|
||||||
* class Child {
|
|
||||||
* // Just asks for RpcService; doesn't know that it's Parent.
|
|
||||||
* constructor(RpcService rpc);
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
publishAs:List;
|
|
||||||
|
|
||||||
@CONST()
|
@CONST()
|
||||||
constructor({
|
constructor({
|
||||||
selector,
|
selector,
|
||||||
@ -892,8 +857,7 @@ export class Component extends Directive {
|
|||||||
injectables,
|
injectables,
|
||||||
lifecycle,
|
lifecycle,
|
||||||
changeDetection = DEFAULT,
|
changeDetection = DEFAULT,
|
||||||
compileChildren = true,
|
compileChildren = true
|
||||||
publishAs
|
|
||||||
}:{
|
}:{
|
||||||
selector:string,
|
selector:string,
|
||||||
properties:Object,
|
properties:Object,
|
||||||
@ -905,8 +869,7 @@ export class Component extends Directive {
|
|||||||
injectables:List,
|
injectables:List,
|
||||||
lifecycle:List,
|
lifecycle:List,
|
||||||
changeDetection:string,
|
changeDetection:string,
|
||||||
compileChildren:boolean,
|
compileChildren:boolean
|
||||||
publishAs:List
|
|
||||||
}={})
|
}={})
|
||||||
{
|
{
|
||||||
super({
|
super({
|
||||||
@ -923,7 +886,6 @@ export class Component extends Directive {
|
|||||||
|
|
||||||
this.changeDetection = changeDetection;
|
this.changeDetection = changeDetection;
|
||||||
this.injectables = injectables;
|
this.injectables = injectables;
|
||||||
this.publishAs = publishAs;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,18 +227,12 @@ export class DirectiveDependency extends Dependency {
|
|||||||
export class DirectiveBinding extends ResolvedBinding {
|
export class DirectiveBinding extends ResolvedBinding {
|
||||||
resolvedInjectables:List<ResolvedBinding>;
|
resolvedInjectables:List<ResolvedBinding>;
|
||||||
metadata: DirectiveMetadata;
|
metadata: DirectiveMetadata;
|
||||||
publishAs: List<Type>;
|
|
||||||
|
|
||||||
constructor(key:Key, factory:Function, dependencies:List, providedAsPromise:boolean,
|
constructor(key:Key, factory:Function, dependencies:List, providedAsPromise:boolean,
|
||||||
resolvedInjectables:List<ResolvedBinding>, metadata:DirectiveMetadata, annotation: Directive) {
|
resolvedInjectables:List<ResolvedBinding>, metadata:DirectiveMetadata, annotation: Directive) {
|
||||||
super(key, factory, dependencies, providedAsPromise);
|
super(key, factory, dependencies, providedAsPromise);
|
||||||
this.resolvedInjectables = resolvedInjectables;
|
this.resolvedInjectables = resolvedInjectables;
|
||||||
this.metadata = metadata;
|
this.metadata = metadata;
|
||||||
if (annotation instanceof Component) {
|
|
||||||
this.publishAs = annotation.publishAs;
|
|
||||||
} else {
|
|
||||||
this.publishAs = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get callOnDestroy() {
|
get callOnDestroy() {
|
||||||
@ -678,20 +672,6 @@ export class ElementInjector extends TreeNode {
|
|||||||
|
|
||||||
var p = this._proto;
|
var p = this._proto;
|
||||||
if (isPresent(p._keyId0)) this._getDirectiveByKeyId(p._keyId0);
|
if (isPresent(p._keyId0)) this._getDirectiveByKeyId(p._keyId0);
|
||||||
if (isPresent(shadowDomAppInjector)) {
|
|
||||||
var publishAs = this._proto._binding0.publishAs;
|
|
||||||
if (isPresent(publishAs) && publishAs.length > 0) {
|
|
||||||
// If there's a component directive on this element injector, then
|
|
||||||
// 0-th key must contain the directive itself.
|
|
||||||
// TODO(yjbanov): need to make injector creation faster:
|
|
||||||
// - remove flattening of bindings array
|
|
||||||
// - precalc token key
|
|
||||||
this._shadowDomAppInjector = shadowDomAppInjector.resolveAndCreateChild(
|
|
||||||
ListWrapper.map(publishAs, (token) => {
|
|
||||||
return bind(token).toValue(this.getComponent());
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isPresent(p._keyId1)) this._getDirectiveByKeyId(p._keyId1);
|
if (isPresent(p._keyId1)) this._getDirectiveByKeyId(p._keyId1);
|
||||||
if (isPresent(p._keyId2)) this._getDirectiveByKeyId(p._keyId2);
|
if (isPresent(p._keyId2)) this._getDirectiveByKeyId(p._keyId2);
|
||||||
if (isPresent(p._keyId3)) this._getDirectiveByKeyId(p._keyId3);
|
if (isPresent(p._keyId3)) this._getDirectiveByKeyId(p._keyId3);
|
||||||
|
@ -195,30 +195,6 @@ class TestNode extends TreeNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TypeScript erases interfaces, so it has to be a class
|
|
||||||
class ParentInterface {}
|
|
||||||
|
|
||||||
class ParentComponent extends ParentInterface {
|
|
||||||
}
|
|
||||||
|
|
||||||
class AppDependency {
|
|
||||||
parent:ParentInterface;
|
|
||||||
|
|
||||||
constructor(p:ParentInterface) {
|
|
||||||
this.parent = p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ChildComponent {
|
|
||||||
parent:ParentInterface;
|
|
||||||
appDependency:AppDependency;
|
|
||||||
|
|
||||||
constructor(p:ParentInterface, a:AppDependency) {
|
|
||||||
this.parent = p;
|
|
||||||
this.appDependency = a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
var defaultPreBuiltObjects = new PreBuiltObjects(null, null, null);
|
var defaultPreBuiltObjects = new PreBuiltObjects(null, null, null);
|
||||||
var appInjector = Injector.resolveAndCreate([]);
|
var appInjector = Injector.resolveAndCreate([]);
|
||||||
@ -647,31 +623,6 @@ export function main() {
|
|||||||
inj.clearDirectives();
|
inj.clearDirectives();
|
||||||
expect(destroy.onDestroyCounter).toBe(1);
|
expect(destroy.onDestroyCounter).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should publish component to its children via app injector when requested", function() {
|
|
||||||
var parentDirective = new Component({
|
|
||||||
selector: 'parent',
|
|
||||||
publishAs: [ParentInterface]
|
|
||||||
});
|
|
||||||
var parentBinding = DirectiveBinding.createFromType(ParentComponent, parentDirective);
|
|
||||||
|
|
||||||
var childDirective = new Component({
|
|
||||||
selector: 'child',
|
|
||||||
injectables: [AppDependency]
|
|
||||||
});
|
|
||||||
var childBinding = DirectiveBinding.createFromType(ChildComponent, childDirective);
|
|
||||||
|
|
||||||
var child = hostShadowInjectors([parentBinding], [childBinding], true, true);
|
|
||||||
var d = child.get(ChildComponent);
|
|
||||||
|
|
||||||
// Verify that the child component can inject parent via interface binding
|
|
||||||
expect(d).toBeAnInstanceOf(ChildComponent);
|
|
||||||
expect(d.parent).toBeAnInstanceOf(ParentComponent);
|
|
||||||
|
|
||||||
// Verify that the binding is available down the dependency tree
|
|
||||||
expect(d.appDependency.parent).toBeAnInstanceOf(ParentComponent);
|
|
||||||
expect(d.parent).toBe(d.appDependency.parent);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("dynamicallyCreateComponent", () => {
|
describe("dynamicallyCreateComponent", () => {
|
||||||
|
@ -986,71 +986,6 @@ export function main() {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('dependency injection', () => {
|
|
||||||
|
|
||||||
it('should publish parent component to shadow DOM via publishAs',
|
|
||||||
inject([TestBed, AsyncTestCompleter, Compiler], (tb, async, compiler) => {
|
|
||||||
tb.overrideView(MyComp, new View({
|
|
||||||
template: `<parent></parent>`,
|
|
||||||
directives: [ParentComponent]
|
|
||||||
}));
|
|
||||||
|
|
||||||
tb.createView(MyComp).then((view) => {
|
|
||||||
view.detectChanges();
|
|
||||||
expect(view.rootNodes).toHaveText(
|
|
||||||
'Parent,Parent');
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should override parent bindings via publishAs',
|
|
||||||
inject([TestBed, AsyncTestCompleter, Compiler], (tb, async, compiler) => {
|
|
||||||
tb.overrideView(MyComp, new View({
|
|
||||||
template: `<recursive-parent></recursive-parent>`,
|
|
||||||
directives: [RecursiveParentComponent]
|
|
||||||
}));
|
|
||||||
|
|
||||||
tb.createView(MyComp).then((view) => {
|
|
||||||
view.detectChanges();
|
|
||||||
expect(view.rootNodes).toHaveText(
|
|
||||||
'ParentInterface,RecursiveParent,RecursiveParent');
|
|
||||||
async.done();
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
// [DynamicComponentLoader] already supports providing a custom
|
|
||||||
// injector as an argument to `loadIntoExistingLocation`, which should
|
|
||||||
// be used instead of `publishAs`.
|
|
||||||
//
|
|
||||||
// Conceptually dynamically loaded components are loaded _instead_ of
|
|
||||||
// the dynamic component itself. The dynamic component does not own the
|
|
||||||
// shadow DOM. It's the loaded component that creates that shadow DOM.
|
|
||||||
it('should not publish into dynamically instantiated components via publishAs',
|
|
||||||
inject([TestBed, AsyncTestCompleter, Compiler], (tb, async, compiler) => {
|
|
||||||
tb.overrideView(MyComp, new View({
|
|
||||||
template: `<dynamic-parent #cmp></dynamic-parent>`,
|
|
||||||
directives: [DynamicParentComponent]
|
|
||||||
}));
|
|
||||||
|
|
||||||
tb.createView(MyComp).then((view) => {
|
|
||||||
view.detectChanges();
|
|
||||||
var comp = view.rawView.locals.get("cmp");
|
|
||||||
PromiseWrapper.then(comp.done,
|
|
||||||
(value) => {
|
|
||||||
throw new BaseException(`Expected to throw error, but got value ${value}`);
|
|
||||||
},
|
|
||||||
(err) => {
|
|
||||||
expect(err.message)
|
|
||||||
.toEqual('No provider for ParentInterface! (ChildComponent -> ParentInterface)');
|
|
||||||
async.done();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1479,70 +1414,6 @@ class NeedsPublicApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ParentInterface {
|
|
||||||
message:String;
|
|
||||||
constructor() {
|
|
||||||
this.message = 'ParentInterface';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'parent',
|
|
||||||
publishAs: [ParentInterface]
|
|
||||||
})
|
|
||||||
@View({
|
|
||||||
template: `<child></child>`,
|
|
||||||
directives: [ChildComponent]
|
|
||||||
})
|
|
||||||
class ParentComponent extends ParentInterface {
|
|
||||||
message:String;
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.message = 'Parent';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
injectables: [ParentInterface],
|
|
||||||
selector: 'recursive-parent',
|
|
||||||
publishAs: [ParentInterface]
|
|
||||||
})
|
|
||||||
@View({
|
|
||||||
template: `{{parentService.message}},<child></child>`,
|
|
||||||
directives: [ChildComponent]
|
|
||||||
})
|
|
||||||
class RecursiveParentComponent extends ParentInterface {
|
|
||||||
parentService:ParentInterface;
|
|
||||||
message:String;
|
|
||||||
constructor(parentService:ParentInterface) {
|
|
||||||
super();
|
|
||||||
this.message = 'RecursiveParent';
|
|
||||||
this.parentService = parentService;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'dynamic-parent',
|
|
||||||
publishAs: [ParentInterface]
|
|
||||||
})
|
|
||||||
class DynamicParentComponent extends ParentInterface {
|
|
||||||
message:String;
|
|
||||||
done;
|
|
||||||
constructor(loader:DynamicComponentLoader, location:ElementRef) {
|
|
||||||
super();
|
|
||||||
this.message = 'DynamicParent';
|
|
||||||
this.done = loader.loadIntoExistingLocation(ChildComponent, location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class AppDependency {
|
|
||||||
parent:ParentInterface;
|
|
||||||
|
|
||||||
constructor(p:ParentInterface) {
|
|
||||||
this.parent = p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'child',
|
selector: 'child',
|
||||||
injectables: [AppDependency]
|
injectables: [AppDependency]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user