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/angular_spec.dart b/test/angular_spec.dart index 5b6d4e5de..bd84d6dec 100644 --- a/test/angular_spec.dart +++ b/test/angular_spec.dart @@ -3,7 +3,6 @@ library angular_spec; import 'dart:mirrors'; import '_specs.dart'; -import 'package:angular/utils.dart'; import 'package:angular/tools/symbol_inspector/symbol_inspector.dart'; main() { @@ -16,34 +15,6 @@ main() { }); }); - describe('relaxFnApply', () { - it('should work with 6 arguments', () { - var sixArgs = [1, 1, 2, 3, 5, 8]; - expect(relaxFnApply(() => "none", sixArgs)).toEqual("none"); - expect(relaxFnApply((a) => a, sixArgs)).toEqual(1); - expect(relaxFnApply((a, b) => a + b, sixArgs)).toEqual(2); - expect(relaxFnApply((a, b, c) => a + b + c, sixArgs)).toEqual(4); - expect(relaxFnApply((a, b, c, d) => a + b + c + d, sixArgs)).toEqual(7); - expect(relaxFnApply((a, b, c, d, e) => a + b + c + d + e, sixArgs)).toEqual(12); - }); - - it('should work with 0 arguments', () { - var noArgs = []; - expect(relaxFnApply(() => "none", noArgs)).toEqual("none"); - expect(relaxFnApply(([a]) => a, noArgs)).toEqual(null); - expect(relaxFnApply(([a, b]) => b, noArgs)).toEqual(null); - expect(relaxFnApply(([a, b, c]) => c, noArgs)).toEqual(null); - expect(relaxFnApply(([a, b, c, d]) => d, noArgs)).toEqual(null); - expect(relaxFnApply(([a, b, c, d, e]) => e, noArgs)).toEqual(null); - }); - - it('should fail with not enough arguments', () { - expect(() { - relaxFnApply((required, alsoRequired) => "happy", [1]); - }).toThrowWith(message: 'Unknown function type, expecting 0 to 5 args.'); - }); - }); - describe('symbols', () { it('should not export unknown symbols from animate', () { LibraryInfo libraryInfo; 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 new file mode 100644 index 000000000..61e4c3ef6 --- /dev/null +++ b/test/utils_spec.dart @@ -0,0 +1,49 @@ +library utils_spec; + +import '_specs.dart'; +import 'package:angular/utils.dart'; + +main() { + describe('relaxFnApply', () { + it('should work with 6 arguments', () { + var sixArgs = [1, 1, 2, 3, 5, 8]; + expect(relaxFnApply(() => "none", sixArgs)).toEqual("none"); + expect(relaxFnApply((a) => a, sixArgs)).toEqual(1); + expect(relaxFnApply((a, b) => a + b, sixArgs)).toEqual(2); + expect(relaxFnApply((a, b, c) => a + b + c, sixArgs)).toEqual(4); + expect(relaxFnApply((a, b, c, d) => a + b + c + d, sixArgs)).toEqual(7); + expect(relaxFnApply((a, b, c, d, e) => a + b + c + d + e, sixArgs)).toEqual(12); + }); + + it('should work with 0 arguments', () { + var noArgs = []; + expect(relaxFnApply(() => "none", noArgs)).toEqual("none"); + expect(relaxFnApply(([a]) => a, noArgs)).toEqual(null); + expect(relaxFnApply(([a, b]) => b, noArgs)).toEqual(null); + expect(relaxFnApply(([a, b, c]) => c, noArgs)).toEqual(null); + expect(relaxFnApply(([a, b, c, d]) => d, noArgs)).toEqual(null); + expect(relaxFnApply(([a, b, c, d, e]) => e, noArgs)).toEqual(null); + }); + + it('should fail with not enough arguments', () { + expect(() { + relaxFnApply((required, alsoRequired) => "happy", [1]); + }).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'); + }); + }); +} +