Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.

fix(compiler): Support camelCase property bindings #1462

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/core_dom/element_binder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions lib/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perf: only the first part need to be lowercased

if (part.length <= 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: should be on one line or use {}

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);
Expand Down
29 changes: 0 additions & 29 deletions test/angular_spec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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;
Expand Down
19 changes: 13 additions & 6 deletions test/core_dom/web_components_spec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,29 +58,36 @@ main() {


it('should bind to Custom Element properties', () {
registerElement('tests-bound', {'prop-y': 10});
registerElement('tests-bound', {'propY': 10});
compileAndUpgrade('<tests-bound bind-prop-y=27></tests-bound>');

// 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('<tests-empty bind-new-prop=27></tests-empty>');
compileAndUpgrade('<tests-empty bind-newprop=27></tests-empty>');
_.rootScope.apply();
expect(customProp('new-prop')).toEqual(27);
expect(customProp('newprop')).toEqual(27);
});

it('should bind to a camelCase property', () {
registerElement('tests-camel', {});
compileAndUpgrade('<tests-camel bind-new-prop=27></tests-camel>');
_.rootScope.apply();
expect(customProp('newProp')).toEqual(27);
});

it('should bind to both directives and properties', () {
registerElement('tests-double', {});
compileAndUpgrade('<tests-double ng-bind bind-ng-bind="\'hello\'"></tests-double>');
_.rootScope.apply();
expect(customProp('ng-bind')).toEqual("hello");
expect(customProp('ngBind')).toEqual("hello");
expect(_.rootElement).toHaveText('hello');
});

Expand Down
49 changes: 49 additions & 0 deletions test/utils_spec.dart
Original file line number Diff line number Diff line change
@@ -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');
});
});
}