refactor(ElementBinder): Store componentDirective and templateDirective as well.
This commit is contained in:
parent
352b6406ad
commit
5e0ff2cbb7
|
@ -17,7 +17,7 @@ export class Component extends Directive {
|
|||
template:TemplateConfig,
|
||||
lightDomServices:DomServicesFunction,
|
||||
shadowDomServices:DomServicesFunction,
|
||||
componentServices:ComponentServicesFunction,
|
||||
componentServices:Array,
|
||||
implementsTypes:Array<Type>
|
||||
}={})
|
||||
{
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
import {ProtoElementInjector} from './element_injector';
|
||||
import {FIELD} from 'facade/lang';
|
||||
import {AnnotatedType} from './annotated_type';
|
||||
// Comment out as dartanalyzer does not look into @FIELD
|
||||
// import {List} from 'facade/collection';
|
||||
// import {ProtoView} from './view';
|
||||
|
||||
export class ElementBinder {
|
||||
@FIELD('final protoElementInjector:ProtoElementInjector')
|
||||
@FIELD('final componentDirective:AnnotatedType')
|
||||
@FIELD('final templateDirective:AnnotatedType')
|
||||
@FIELD('final textNodeIndices:List<int>')
|
||||
@FIELD('hasElementPropertyBindings:bool')
|
||||
@FIELD('nestedProtoView:ProtoView')
|
||||
constructor(protoElementInjector: ProtoElementInjector) {
|
||||
constructor(protoElementInjector: ProtoElementInjector, componentDirective:AnnotatedType, templateDirective:AnnotatedType) {
|
||||
this.protoElementInjector = protoElementInjector;
|
||||
this.componentDirective = componentDirective;
|
||||
this.templateDirective = templateDirective;
|
||||
// updated later when text nodes are bound
|
||||
this.textNodeIndices = [];
|
||||
// updated later when element properties are bound
|
||||
|
|
|
@ -52,7 +52,8 @@ export class ElementBinderBuilder extends CompileStep {
|
|||
var elementBinder;
|
||||
if (current.hasBindings) {
|
||||
var protoView = current.inheritedProtoView;
|
||||
elementBinder = protoView.bindElement(current.inheritedProtoElementInjector);
|
||||
elementBinder = protoView.bindElement(current.inheritedProtoElementInjector,
|
||||
current.componentDirective, current.templateDirective);
|
||||
|
||||
if (isPresent(current.textNodeBindings)) {
|
||||
this._bindTextNodes(protoView, current.textNodeBindings);
|
||||
|
|
|
@ -3,8 +3,10 @@ import {ListWrapper} from 'facade/collection';
|
|||
import {ProtoWatchGroup, WatchGroup, WatchGroupDispatcher} from 'change_detection/watch_group';
|
||||
import {Record} from 'change_detection/record';
|
||||
import {AST} from 'change_detection/parser/ast';
|
||||
|
||||
import {ProtoElementInjector, ElementInjector} from './element_injector';
|
||||
import {ElementBinder} from './element_binder';
|
||||
import {AnnotatedType} from './annotated_type';
|
||||
import {SetterFn} from 'change_detection/parser/closure_map';
|
||||
import {FIELD, IMPLEMENTS, int, isPresent, isBlank} from 'facade/lang';
|
||||
import {List} from 'facade/collection';
|
||||
|
@ -99,8 +101,9 @@ export class ProtoView {
|
|||
bindElements, this.protoWatchGroup, context);
|
||||
}
|
||||
|
||||
bindElement(protoElementInjector:ProtoElementInjector):ElementBinder {
|
||||
var elBinder = new ElementBinder(protoElementInjector);
|
||||
bindElement(protoElementInjector:ProtoElementInjector,
|
||||
componentDirective:AnnotatedType = null, templateDirective:AnnotatedType = null):ElementBinder {
|
||||
var elBinder = new ElementBinder(protoElementInjector, componentDirective, templateDirective);
|
||||
ListWrapper.push(this.elementBinders, elBinder);
|
||||
return elBinder;
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ export function main() {
|
|||
});
|
||||
|
||||
it('should store the current protoElementInjector', () => {
|
||||
var directives = [SomeSimpleDirective];
|
||||
var directives = [SomeDecoratorDirective];
|
||||
var protoElementInjector = new ProtoElementInjector(null, 0, directives);
|
||||
|
||||
var pipeline = createPipeline({protoElementInjector: protoElementInjector, directives: directives});
|
||||
|
@ -110,6 +110,24 @@ export function main() {
|
|||
expect(pv.elementBinders[0].protoElementInjector).toBe(protoElementInjector);
|
||||
});
|
||||
|
||||
it('should store the component directive', () => {
|
||||
var directives = [SomeComponentDirective];
|
||||
var pipeline = createPipeline({protoElementInjector: null, directives: directives});
|
||||
var results = pipeline.process(createElement('<div viewroot directives></div>'));
|
||||
var pv = results[0].inheritedProtoView;
|
||||
|
||||
expect(pv.elementBinders[0].componentDirective.type).toBe(SomeComponentDirective);
|
||||
});
|
||||
|
||||
it('should store the template directive', () => {
|
||||
var directives = [SomeTemplateDirective];
|
||||
var pipeline = createPipeline({protoElementInjector: null, directives: directives});
|
||||
var results = pipeline.process(createElement('<div viewroot directives></div>'));
|
||||
var pv = results[0].inheritedProtoView;
|
||||
|
||||
expect(pv.elementBinders[0].templateDirective.type).toBe(SomeTemplateDirective);
|
||||
});
|
||||
|
||||
it('should bind text nodes', () => {
|
||||
var textNodeBindings = MapWrapper.create();
|
||||
MapWrapper.set(textNodeBindings, 0, 'prop1');
|
||||
|
@ -155,7 +173,7 @@ export function main() {
|
|||
'boundprop2': 'prop2',
|
||||
'boundprop3': 'prop3'
|
||||
});
|
||||
var directives = [SomeDecoratorDirective, SomeTemplateDirective, SomeComponentDirective];
|
||||
var directives = [SomeDecoratorDirectiveWithBinding, SomeTemplateDirectiveWithBinding, SomeComponentDirectiveWithBinding];
|
||||
var protoElementInjector = new ProtoElementInjector(null, 0, directives);
|
||||
var pipeline = createPipeline({
|
||||
propertyBindings: propertyBindings,
|
||||
|
@ -171,16 +189,16 @@ export function main() {
|
|||
evalContext.prop3 = 'c';
|
||||
changeDetector.detectChanges();
|
||||
|
||||
expect(view.elementInjectors[0].get(SomeDecoratorDirective).decorProp).toBe('a');
|
||||
expect(view.elementInjectors[0].get(SomeTemplateDirective).templProp).toBe('b');
|
||||
expect(view.elementInjectors[0].get(SomeComponentDirective).compProp).toBe('c');
|
||||
expect(view.elementInjectors[0].get(SomeDecoratorDirectiveWithBinding).decorProp).toBe('a');
|
||||
expect(view.elementInjectors[0].get(SomeTemplateDirectiveWithBinding).templProp).toBe('b');
|
||||
expect(view.elementInjectors[0].get(SomeComponentDirectiveWithBinding).compProp).toBe('c');
|
||||
});
|
||||
|
||||
it('should bind directive properties for sibling elements', () => {
|
||||
var propertyBindings = MapWrapper.createFromStringMap({
|
||||
'boundprop1': 'prop1'
|
||||
});
|
||||
var directives = [SomeDecoratorDirective];
|
||||
var directives = [SomeDecoratorDirectiveWithBinding];
|
||||
var protoElementInjector = new ProtoElementInjector(null, 0, directives);
|
||||
var pipeline = createPipeline({
|
||||
propertyBindings: propertyBindings,
|
||||
|
@ -196,16 +214,16 @@ export function main() {
|
|||
evalContext.prop1 = 'a';
|
||||
changeDetector.detectChanges();
|
||||
|
||||
expect(view.elementInjectors[1].get(SomeDecoratorDirective).decorProp).toBe('a');
|
||||
expect(view.elementInjectors[1].get(SomeDecoratorDirectiveWithBinding).decorProp).toBe('a');
|
||||
});
|
||||
|
||||
describe('errors', () => {
|
||||
|
||||
it('should throw if there is no element property bindings for a directive property binding', () => {
|
||||
var pipeline = createPipeline({propertyBindings: MapWrapper.create(), directives: [SomeDecoratorDirective]});
|
||||
var pipeline = createPipeline({propertyBindings: MapWrapper.create(), directives: [SomeDecoratorDirectiveWithBinding]});
|
||||
expect( () => {
|
||||
pipeline.process(createElement('<div viewroot prop-binding directives>'));
|
||||
}).toThrowError('No element binding found for property boundprop1 which is required by directive SomeDecoratorDirective');
|
||||
}).toThrowError('No element binding found for property boundprop1 which is required by directive SomeDecoratorDirectiveWithBinding');
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -215,31 +233,39 @@ export function main() {
|
|||
}
|
||||
|
||||
@Decorator()
|
||||
class SomeSimpleDirective {
|
||||
class SomeDecoratorDirective {
|
||||
}
|
||||
|
||||
@Decorator({
|
||||
bind: {'boundprop1': 'decorProp'}
|
||||
})
|
||||
class SomeDecoratorDirective {
|
||||
class SomeDecoratorDirectiveWithBinding {
|
||||
constructor() {
|
||||
this.decorProp = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Template()
|
||||
class SomeTemplateDirective {
|
||||
}
|
||||
|
||||
@Template({
|
||||
bind: {'boundprop2': 'templProp'}
|
||||
})
|
||||
class SomeTemplateDirective {
|
||||
class SomeTemplateDirectiveWithBinding {
|
||||
constructor() {
|
||||
this.templProp = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Component()
|
||||
class SomeComponentDirective {
|
||||
}
|
||||
|
||||
@Component({
|
||||
bind: {'boundprop3': 'compProp'}
|
||||
})
|
||||
class SomeComponentDirective {
|
||||
class SomeComponentDirectiveWithBinding {
|
||||
constructor() {
|
||||
this.compProp = null;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ export function main() {
|
|||
if (isPresent(current.element.getAttribute('viewroot'))) {
|
||||
current.isViewRoot = true;
|
||||
}
|
||||
current.inheritedElementBinder = new ElementBinder(null);
|
||||
current.inheritedElementBinder = new ElementBinder(null, null, null);
|
||||
}), new ProtoViewBuilder()]);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue