diff --git a/lib/core_dom/element_binder.dart b/lib/core_dom/element_binder.dart index 756ff889d..6e69b78e9 100644 --- a/lib/core_dom/element_binder.dart +++ b/lib/core_dom/element_binder.dart @@ -308,6 +308,7 @@ class ElementBinder { var jsNode; List bindAssignableProps = []; bindAttrs.forEach((String prop, AST ast) { + prop = camelCase(prop); if (jsNode == null) jsNode = new js.JsObject.fromBrowserObject(node); scope.watchAST(ast, (v, _) { jsNode[prop] = v; diff --git a/lib/utils.dart b/lib/utils.dart index dbaa06ac3..135293cc0 100644 --- a/lib/utils.dart +++ b/lib/utils.dart @@ -81,6 +81,12 @@ relaxFnArgs(Function fn) { capitalize(String s) => s.substring(0, 1).toUpperCase() + s.substring(1); +String camelCase(String s) { + var part = s.split('-').map((s) => s.toLowerCase()); + if (part.length <= 1) + return part.join(); + return part.first + part.skip(1).map(capitalize).join(); +} /// Returns whether or not the given identifier is a reserved word in Dart. bool isReservedWord(String identifier) => RESERVED_WORDS.contains(identifier); diff --git a/test/core_dom/web_components_spec.dart b/test/core_dom/web_components_spec.dart index bdb68278a..7ad9f7198 100644 --- a/test/core_dom/web_components_spec.dart +++ b/test/core_dom/web_components_spec.dart @@ -58,29 +58,36 @@ main() { it('should bind to Custom Element properties', () { - registerElement('tests-bound', {'prop-y': 10}); + registerElement('tests-bound', {'propY': 10}); compileAndUpgrade(''); // Scope has not been digested yet - expect(customProp('prop-y')).toEqual(10); + expect(customProp('propY')).toEqual(10); _.rootScope.apply(); - expect(customProp('prop-y')).toEqual(27); + expect(customProp('propY')).toEqual(27); }); it('should bind to a non-existent property', () { registerElement('tests-empty', {}); - compileAndUpgrade(''); + compileAndUpgrade(''); _.rootScope.apply(); - expect(customProp('new-prop')).toEqual(27); + expect(customProp('newprop')).toEqual(27); + }); + + it('should bind to a camelCase property', () { + registerElement('tests-camel', {}); + compileAndUpgrade(''); + _.rootScope.apply(); + expect(customProp('newProp')).toEqual(27); }); it('should bind to both directives and properties', () { registerElement('tests-double', {}); compileAndUpgrade(''); _.rootScope.apply(); - expect(customProp('ng-bind')).toEqual("hello"); + expect(customProp('ngBind')).toEqual("hello"); expect(_.rootElement).toHaveText('hello'); }); diff --git a/test/utils_spec.dart b/test/utils_spec.dart index 5d09edde3..61e4c3ef6 100644 --- a/test/utils_spec.dart +++ b/test/utils_spec.dart @@ -31,5 +31,19 @@ main() { }).toThrowWith(message: 'Unknown function type, expecting 0 to 5 args.'); }); }); + + describe('camelCase', () { + it('should ignore non camelCase', () { + expect(camelCase('regular')).toEqual('regular'); + }); + + it('should convert snake-case', () { + expect(camelCase('snake-case')).toEqual('snakeCase'); + }); + + it('should lowercase strings', () { + expect(camelCase('Caps-first')).toEqual('capsFirst'); + }); + }); }