fix(compiler): properly bind to properties that don't have matching attr name

Fixes #619
Closes #783
This commit is contained in:
Pawel Kozlowski
2015-02-25 15:30:37 +01:00
parent e490861ba2
commit 7e6f536cf5
5 changed files with 91 additions and 8 deletions

View File

@ -1,5 +1,5 @@
import {int, isPresent, isBlank, Type, BaseException, StringWrapper, RegExpWrapper, isString, stringify} from 'angular2/src/facade/lang';
import {Element, DOM} from 'angular2/src/facade/dom';
import {Element, DOM, attrToPropMap} from 'angular2/src/facade/dom';
import {ListWrapper, List, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
import {reflector} from 'angular2/src/reflection/reflection';
@ -91,11 +91,19 @@ function roleSetter(element:Element, value) {
}
}
// special mapping for cases where attribute name doesn't match property name
var attrToProp = StringMapWrapper.merge({
"inner-html": "innerHTML",
"readonly": "readOnly",
"tabindex": "tabIndex",
}, attrToPropMap);
// tells if an attribute is handled by the ElementBinderBuilder step
export function isSpecialProperty(propName:string) {
return StringWrapper.startsWith(propName, ARIA_PREFIX)
|| StringWrapper.startsWith(propName, CLASS_PREFIX)
|| StringWrapper.startsWith(propName, STYLE_PREFIX);
return StringWrapper.startsWith(propName, ARIA_PREFIX)
|| StringWrapper.startsWith(propName, CLASS_PREFIX)
|| StringWrapper.startsWith(propName, STYLE_PREFIX)
|| StringMapWrapper.contains(attrToProp, propName);
}
/**
@ -176,10 +184,14 @@ export class ElementBinderBuilder extends CompileStep {
setterFn = classSetterFactory(StringWrapper.substring(property, CLASS_PREFIX.length));
} else if (StringWrapper.startsWith(property, STYLE_PREFIX)) {
styleParts = StringWrapper.split(property, DOT_REGEXP);
styleSuffix = styleParts.length > 2 ? ListWrapper.get(styleParts, 2) : '';
styleSuffix = styleParts.length > 2 ? ListWrapper.get(styleParts, 2) : '';
setterFn = styleSetterFactory(ListWrapper.get(styleParts, 1), styleSuffix);
} else if (DOM.hasProperty(compileElement.element, property)) {
setterFn = reflector.setter(property);
} else {
property = this._resolvePropertyName(property);
//TODO(pk): special casing innerHtml, see: https://github.com/angular/angular/issues/789
if (DOM.hasProperty(compileElement.element, property) || StringWrapper.equals(property, 'innerHtml')) {
setterFn = reflector.setter(property);
}
}
if (isPresent(setterFn)) {
@ -236,4 +248,9 @@ export class ElementBinderBuilder extends CompileStep {
var parts = StringWrapper.split(bindConfig, RegExpWrapper.create("\\|"));
return ListWrapper.map(parts, (s) => s.trim());
}
_resolvePropertyName(attrName:string) {
var mappedPropName = StringMapWrapper.get(attrToProp, attrName);
return isPresent(mappedPropName) ? mappedPropName : attrName;
}
}

View File

@ -17,7 +17,8 @@ export 'dart:html' show
InputElement,
AnchorElement,
Text,
window;
window,
attrToPropMap;
// TODO(tbosch): Is there a builtin one? Why is Dart
// removing unknown elements by default?
@ -36,6 +37,11 @@ void gc() {
final identitySanitizer = new IdentitySanitizer();
// override JS logic of attribute to property mapping
var attrToPropMap = {
"inner-html": "innerHtml"
};
class DOM {
static query(String selector) => document.querySelector(selector);

View File

@ -16,6 +16,8 @@ export var gc = window.gc ? () => window.gc() : () => null;
export var CssRule = window.CSSRule;
export var CssKeyframesRule = window.CSSKeyframesRule;
export var attrToPropMap = {};
export class DOM {
static query(selector) {
return document.querySelector(selector);