parent
3ce0f1146f
commit
b1dc6239ef
|
@ -26,3 +26,15 @@ export class PropertySetter extends DependencyAnnotation {
|
||||||
this.propName = propName;
|
this.propName = propName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The directive can inject the value of an attribute of the host element
|
||||||
|
*/
|
||||||
|
export class Attribute extends DependencyAnnotation {
|
||||||
|
attributeName: string;
|
||||||
|
@CONST()
|
||||||
|
constructor(attributeName) {
|
||||||
|
super();
|
||||||
|
this.attributeName = attributeName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {Math} from 'angular2/src/facade/math';
|
||||||
import {List, ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
import {List, ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {Injector, Key, Dependency, bind, Binding, NoProviderError, ProviderError, CyclicDependencyError} from 'angular2/di';
|
import {Injector, Key, Dependency, bind, Binding, NoProviderError, ProviderError, CyclicDependencyError} from 'angular2/di';
|
||||||
import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility';
|
import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility';
|
||||||
import {EventEmitter, PropertySetter} from 'angular2/src/core/annotations/di';
|
import {EventEmitter, PropertySetter, Attribute} from 'angular2/src/core/annotations/di';
|
||||||
import * as viewModule from 'angular2/src/core/compiler/view';
|
import * as viewModule from 'angular2/src/core/compiler/view';
|
||||||
import {ViewContainer} from 'angular2/src/core/compiler/view_container';
|
import {ViewContainer} from 'angular2/src/core/compiler/view_container';
|
||||||
import {NgElement} from 'angular2/src/core/dom/element';
|
import {NgElement} from 'angular2/src/core/dom/element';
|
||||||
|
@ -90,19 +90,22 @@ export class DirectiveDependency extends Dependency {
|
||||||
depth:int;
|
depth:int;
|
||||||
eventEmitterName:string;
|
eventEmitterName:string;
|
||||||
propSetterName:string;
|
propSetterName:string;
|
||||||
|
attributeName:string;
|
||||||
|
|
||||||
constructor(key:Key, asPromise:boolean, lazy:boolean, optional:boolean,
|
constructor(key:Key, asPromise:boolean, lazy:boolean, optional:boolean,
|
||||||
properties:List, depth:int, eventEmitterName: string, propSetterName: string) {
|
properties:List, depth:int, eventEmitterName: string, propSetterName: string, attributeName:string) {
|
||||||
super(key, asPromise, lazy, optional, properties);
|
super(key, asPromise, lazy, optional, properties);
|
||||||
this.depth = depth;
|
this.depth = depth;
|
||||||
this.eventEmitterName = eventEmitterName;
|
this.eventEmitterName = eventEmitterName;
|
||||||
this.propSetterName = propSetterName;
|
this.propSetterName = propSetterName;
|
||||||
|
this.attributeName = attributeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
static createFrom(d:Dependency):Dependency {
|
static createFrom(d:Dependency):Dependency {
|
||||||
var depth = 0;
|
var depth = 0;
|
||||||
var eventName = null;
|
var eventName = null;
|
||||||
var propName = null;
|
var propName = null;
|
||||||
|
var attributeName = null;
|
||||||
var properties = d.properties;
|
var properties = d.properties;
|
||||||
|
|
||||||
for (var i = 0; i < properties.length; i++) {
|
for (var i = 0; i < properties.length; i++) {
|
||||||
|
@ -115,11 +118,13 @@ export class DirectiveDependency extends Dependency {
|
||||||
eventName = property.eventName;
|
eventName = property.eventName;
|
||||||
} else if (property instanceof PropertySetter) {
|
} else if (property instanceof PropertySetter) {
|
||||||
propName = property.propName;
|
propName = property.propName;
|
||||||
|
} else if (property instanceof Attribute) {
|
||||||
|
attributeName = property.attributeName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DirectiveDependency(d.key, d.asPromise, d.lazy, d.optional, d.properties, depth,
|
return new DirectiveDependency(d.key, d.asPromise, d.lazy, d.optional, d.properties, depth,
|
||||||
eventName, propName);
|
eventName, propName, attributeName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,6 +214,7 @@ export class ProtoElementInjector {
|
||||||
index:int;
|
index:int;
|
||||||
view:viewModule.View;
|
view:viewModule.View;
|
||||||
distanceToParent:number;
|
distanceToParent:number;
|
||||||
|
attributes:Map;
|
||||||
|
|
||||||
/** Whether the element is exported as $implicit. */
|
/** Whether the element is exported as $implicit. */
|
||||||
exportElement:boolean;
|
exportElement:boolean;
|
||||||
|
@ -514,6 +520,7 @@ export class ElementInjector extends TreeNode {
|
||||||
_getByDependency(dep:DirectiveDependency, requestor:Key) {
|
_getByDependency(dep:DirectiveDependency, requestor:Key) {
|
||||||
if (isPresent(dep.eventEmitterName)) return this._buildEventEmitter(dep);
|
if (isPresent(dep.eventEmitterName)) return this._buildEventEmitter(dep);
|
||||||
if (isPresent(dep.propSetterName)) return this._buildPropSetter(dep);
|
if (isPresent(dep.propSetterName)) return this._buildPropSetter(dep);
|
||||||
|
if (isPresent(dep.attributeName)) return this._buildAttribute(dep);
|
||||||
return this._getByKey(dep.key, dep.depth, dep.optional, requestor);
|
return this._getByKey(dep.key, dep.depth, dep.optional, requestor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,6 +538,15 @@ export class ElementInjector extends TreeNode {
|
||||||
return function(v) { setter(domElement, v) };
|
return function(v) { setter(domElement, v) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_buildAttribute(dep): string {
|
||||||
|
var attributes = this._proto.attributes;
|
||||||
|
if (isPresent(attributes) && MapWrapper.contains(attributes, dep.attributeName)) {
|
||||||
|
return MapWrapper.get(attributes, dep.attributeName);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It is fairly easy to annotate keys with metadata.
|
* It is fairly easy to annotate keys with metadata.
|
||||||
* For example, key.metadata = 'directive'.
|
* For example, key.metadata = 'directive'.
|
||||||
|
|
|
@ -22,6 +22,7 @@ export class CompileElement {
|
||||||
textNodeBindings:Map;
|
textNodeBindings:Map;
|
||||||
propertyBindings:Map;
|
propertyBindings:Map;
|
||||||
eventBindings:Map;
|
eventBindings:Map;
|
||||||
|
attributes:Map;
|
||||||
|
|
||||||
/// Store directive name to template name mapping.
|
/// Store directive name to template name mapping.
|
||||||
/// Directive name is what the directive exports the variable as
|
/// Directive name is what the directive exports the variable as
|
||||||
|
@ -144,6 +145,13 @@ export class CompileElement {
|
||||||
MapWrapper.set(this.eventBindings, eventName, expression);
|
MapWrapper.set(this.eventBindings, eventName, expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addAttribute(attributeName:string, attributeValue:string) {
|
||||||
|
if (isBlank(this.attributes)) {
|
||||||
|
this.attributes = MapWrapper.create();
|
||||||
|
}
|
||||||
|
MapWrapper.set(this.attributes, attributeName, attributeValue);
|
||||||
|
}
|
||||||
|
|
||||||
addDirective(directive:DirectiveMetadata) {
|
addDirective(directive:DirectiveMetadata) {
|
||||||
var annotation = directive.annotation;
|
var annotation = directive.annotation;
|
||||||
this._allDirectives = null;
|
this._allDirectives = null;
|
||||||
|
|
|
@ -72,6 +72,8 @@ export class PropertyBindingParser extends CompileStep {
|
||||||
var ast = this._parseInterpolation(attrValue, desc);
|
var ast = this._parseInterpolation(attrValue, desc);
|
||||||
if (isPresent(ast)) {
|
if (isPresent(ast)) {
|
||||||
current.addPropertyBinding(attrName, ast);
|
current.addPropertyBinding(attrName, ast);
|
||||||
|
} else {
|
||||||
|
current.addAttribute(attrName, attrValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -59,6 +59,7 @@ export class ProtoElementInjectorBuilder extends CompileStep {
|
||||||
current.inheritedProtoElementInjector.exportImplicitName = exportImplicitName;
|
current.inheritedProtoElementInjector.exportImplicitName = exportImplicitName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
current.inheritedProtoElementInjector.attributes = current.attributes;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
current.inheritedProtoElementInjector = parentProtoElementInjector;
|
current.inheritedProtoElementInjector = parentProtoElementInjector;
|
||||||
|
|
|
@ -136,6 +136,8 @@ function _extractToken(typeOrFunc, annotations) {
|
||||||
|
|
||||||
} else if (paramAnnotation instanceof DependencyAnnotation) {
|
} else if (paramAnnotation instanceof DependencyAnnotation) {
|
||||||
ListWrapper.push(depProps, paramAnnotation);
|
ListWrapper.push(depProps, paramAnnotation);
|
||||||
|
} else if (paramAnnotation.name === "string") {
|
||||||
|
token = paramAnnotation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import {ListWrapper, MapWrapper, List, StringMapWrapper} from 'angular2/src/faca
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
import {ProtoElementInjector, PreBuiltObjects, DirectiveBinding} from 'angular2/src/core/compiler/element_injector';
|
import {ProtoElementInjector, PreBuiltObjects, DirectiveBinding} from 'angular2/src/core/compiler/element_injector';
|
||||||
import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility';
|
import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility';
|
||||||
import {EventEmitter, PropertySetter} from 'angular2/src/core/annotations/di';
|
import {EventEmitter, PropertySetter, Attribute} from 'angular2/src/core/annotations/di';
|
||||||
import {onDestroy} from 'angular2/src/core/annotations/annotations';
|
import {onDestroy} from 'angular2/src/core/annotations/annotations';
|
||||||
import {Optional, Injector, Inject, bind} from 'angular2/di';
|
import {Optional, Injector, Inject, bind} from 'angular2/di';
|
||||||
import {ProtoView, View} from 'angular2/src/core/compiler/view';
|
import {ProtoView, View} from 'angular2/src/core/compiler/view';
|
||||||
|
@ -107,6 +107,17 @@ class NeedsPropertySetter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class NeedsAttribute {
|
||||||
|
typeAttribute;
|
||||||
|
titleAttribute;
|
||||||
|
fooAttribute;
|
||||||
|
constructor(@Attribute('type') typeAttribute: string, @Attribute('title') titleAttribute: string, @Attribute('foo') fooAttribute: string) {
|
||||||
|
this.typeAttribute = typeAttribute;
|
||||||
|
this.titleAttribute = titleAttribute;
|
||||||
|
this.fooAttribute = fooAttribute;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class A_Needs_B {
|
class A_Needs_B {
|
||||||
constructor(dep){}
|
constructor(dep){}
|
||||||
}
|
}
|
||||||
|
@ -148,10 +159,11 @@ export function main() {
|
||||||
return [lookupName(tree), children];
|
return [lookupName(tree), children];
|
||||||
}
|
}
|
||||||
|
|
||||||
function injector(bindings, lightDomAppInjector = null, shadowDomAppInjector = null, preBuiltObjects = null) {
|
function injector(bindings, lightDomAppInjector = null, shadowDomAppInjector = null, preBuiltObjects = null, attributes = null) {
|
||||||
if (isBlank(lightDomAppInjector)) lightDomAppInjector = appInjector;
|
if (isBlank(lightDomAppInjector)) lightDomAppInjector = appInjector;
|
||||||
|
|
||||||
var proto = new ProtoElementInjector(null, 0, bindings, isPresent(shadowDomAppInjector));
|
var proto = new ProtoElementInjector(null, 0, bindings, isPresent(shadowDomAppInjector));
|
||||||
|
proto.attributes = attributes;
|
||||||
var inj = proto.instantiate(null, null);
|
var inj = proto.instantiate(null, null);
|
||||||
var preBuilt = isPresent(preBuiltObjects) ? preBuiltObjects : defaultPreBuiltObjects;
|
var preBuilt = isPresent(preBuiltObjects) ? preBuiltObjects : defaultPreBuiltObjects;
|
||||||
|
|
||||||
|
@ -566,5 +578,20 @@ export function main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('static', () => {
|
||||||
|
it('should be injectable', () => {
|
||||||
|
var attributes = MapWrapper.create();
|
||||||
|
MapWrapper.set(attributes, 'type', 'text');
|
||||||
|
MapWrapper.set(attributes, 'title', '');
|
||||||
|
|
||||||
|
var inj = injector([NeedsAttribute], null, null, null, attributes);
|
||||||
|
var needsAttribute = inj.get(NeedsAttribute);
|
||||||
|
|
||||||
|
expect(needsAttribute.typeAttribute).toEqual('text');
|
||||||
|
expect(needsAttribute.titleAttribute).toEqual('');
|
||||||
|
expect(needsAttribute.fooAttribute).toEqual(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ import {EventManager} from 'angular2/src/core/events/event_manager';
|
||||||
import {Decorator, Component, Viewport, DynamicComponent} from 'angular2/src/core/annotations/annotations';
|
import {Decorator, Component, Viewport, DynamicComponent} from 'angular2/src/core/annotations/annotations';
|
||||||
import {Template} from 'angular2/src/core/annotations/template';
|
import {Template} from 'angular2/src/core/annotations/template';
|
||||||
import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility';
|
import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility';
|
||||||
import {EventEmitter} from 'angular2/src/core/annotations/di';
|
import {EventEmitter, Attribute} from 'angular2/src/core/annotations/di';
|
||||||
|
|
||||||
import {If} from 'angular2/src/directives/if';
|
import {If} from 'angular2/src/directives/if';
|
||||||
|
|
||||||
|
@ -606,6 +606,26 @@ export function main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it('should support static attributes', inject([AsyncTestCompleter], (async) => {
|
||||||
|
tplResolver.setTemplate(MyComp, new Template({
|
||||||
|
inline: '<input static type="text" title></input>',
|
||||||
|
directives: [NeedsAttribute]
|
||||||
|
}));
|
||||||
|
compiler.compile(MyComp).then((pv) => {
|
||||||
|
createView(pv);
|
||||||
|
|
||||||
|
var injector = view.elementInjectors[0];
|
||||||
|
var needsAttribute = injector.get(NeedsAttribute);
|
||||||
|
expect(needsAttribute.typeAttribute).toEqual('text');
|
||||||
|
expect(needsAttribute.titleAttribute).toEqual('');
|
||||||
|
expect(needsAttribute.fooAttribute).toEqual(null);
|
||||||
|
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Disabled until a solution is found, refs:
|
// Disabled until a solution is found, refs:
|
||||||
|
@ -902,3 +922,17 @@ class DecoratorListeningEvent {
|
||||||
class IdComponent {
|
class IdComponent {
|
||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Decorator({
|
||||||
|
selector: '[static]'
|
||||||
|
})
|
||||||
|
class NeedsAttribute {
|
||||||
|
typeAttribute;
|
||||||
|
titleAttribute;
|
||||||
|
fooAttribute;
|
||||||
|
constructor(@Attribute('type') typeAttribute: string, @Attribute('title') titleAttribute: string, @Attribute('foo') fooAttribute: string) {
|
||||||
|
this.typeAttribute = typeAttribute;
|
||||||
|
this.titleAttribute = titleAttribute;
|
||||||
|
this.fooAttribute = fooAttribute;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -46,6 +46,12 @@ export function main() {
|
||||||
expect(MapWrapper.get(results[0].propertyBindings, 'a').source).toEqual('{{b}}');
|
expect(MapWrapper.get(results[0].propertyBindings, 'a').source).toEqual('{{b}}');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should detect static attributes', () => {
|
||||||
|
var results = createPipeline().process(el('<div a="b" c></div>'));
|
||||||
|
expect(MapWrapper.get(results[0].attributes, 'a')).toEqual('b');
|
||||||
|
expect(MapWrapper.get(results[0].attributes, 'c')).toEqual('');
|
||||||
|
});
|
||||||
|
|
||||||
it('should detect var- syntax', () => {
|
it('should detect var- syntax', () => {
|
||||||
var results = createPipeline().process(el('<template var-a="b"></template>'));
|
var results = createPipeline().process(el('<template var-a="b"></template>'));
|
||||||
expect(MapWrapper.get(results[0].variableBindings, 'b')).toEqual('a');
|
expect(MapWrapper.get(results[0].variableBindings, 'b')).toEqual('a');
|
||||||
|
|
Loading…
Reference in New Issue