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

Commit

Permalink
feat(element binder): Two way binding for Web Components
Browse files Browse the repository at this point in the history
Closes #1282
  • Loading branch information
jbdeboer committed Jul 31, 2014
1 parent 65fc117 commit 4633451
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 4 deletions.
14 changes: 12 additions & 2 deletions example/web/paper.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,18 @@
href="bower_components/paper-progress/paper-progress.html">
<link rel="import"
href="bower_components/paper-checkbox/paper-checkbox.html">
<link rel="import"
href="bower_components/paper-slider/paper-slider.html">
<script type="application/dart" src="paper.dart"></script>
<script src="packages/browser/dart.js"></script>
<style>
div { padding: 0.25em; }
paper-slider { width: 40em; }
</style>
</head>
<body>
<h1>Polymer components inside a AngularDart app</h1>
<h2>paper-progress</h2>
<h2>Property binding: paper-progress</h2>
<p>This is a simple component that doesn't generate events; the only things that is required is property binding</p>
<p>The max ({{max}}) and value ({{curValue}}) properties are bound through bind-* semantics</p>

Expand All @@ -37,13 +40,20 @@ <h2>paper-progress</h2>
</label>
</p>

<h2>paper-checkbox</h2>
<h2>Events: paper-checkbox</h2>
<p>The checkbox will generate an event every time the value is changed</p>
<p>AngularDart can listen to these events through the on-* syntax</p>

<div>
<paper-checkbox on-change="curValue = curValue == 5 ? 2 : curValue == 2 ? 10 : 5"></paper-checkbox>
</div>
<p>Every the value changes, the curValue ({{curValue}}) scope variable will update</p>

<h2>Two-way binding: paper-slider</h2>
<p>The slide is bound to the curValue scope variable ({{curValue}})</p>

<div>
<paper-slider min="0" bind-max="max" bind-value="curValue" pin="true"></paper-slider>
</div>
</body>
</html>
15 changes: 14 additions & 1 deletion lib/core_dom/element_binder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -284,13 +284,26 @@ class ElementBinder {
_link(nodeInjector, scope, nodeAttrs);

var jsNode;
bindAttrs.forEach((String prop, ast) {
List bindAssignableProps = [];
bindAttrs.forEach((String prop, AST ast) {
if (jsNode == null) jsNode = new js.JsObject.fromBrowserObject(node);
scope.watchAST(ast, (v, _) {
jsNode[prop] = v;
});

if (ast.parsedExp.isAssignable) {
bindAssignableProps.add([prop, ast.parsedExp]);
}
});

if (bindAssignableProps.isNotEmpty) {
node.addEventListener('change', (_) {
bindAssignableProps.forEach((propAndExp) {
propAndExp[1].assign(scope.context, jsNode[propAndExp[0]]);
});
});
}

if (onEvents.isNotEmpty) {
onEvents.forEach((event, value) {
view.registerEvent(EventHandler.attrNameToEventName(event));
Expand Down
25 changes: 24 additions & 1 deletion test/core_dom/web_components_spec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,24 @@ main() {
describe('WebComponent support', () {
TestBed _;

customProp(String prop, [elt]) {
/**
* Returns the property [prop] as read through the JS interface.
* [elt] is optional and defaults to the [TestBed]'s rootElement.
*/
customProp(String prop, [Element elt]) {
if (elt == null) elt = _.rootElement;
return (new js.JsObject.fromBrowserObject(elt))[prop];
}

/**
* Sets the property [prop] to [value] through the JS interface.
* [elt] is optional and defaults to the [TestBed]'s rootElement.
*/
void setCustomProp(String prop, value, [Element elt]) {
if (elt == null) elt = _.rootElement;
(new js.JsObject.fromBrowserObject(_.rootElement))[prop] = value;
}

beforeEach((TestBed tb) {
_ = tb;
});
Expand Down Expand Up @@ -58,5 +71,15 @@ main() {
expect(customProp('ng-bind')).toEqual("hello");
expect(_.rootElement).toHaveText('hello');
});

it('should support two-way bindings for components that trigger a change event', () {
registerElement('tests-twoway', {});
_.compile('<tests-twoway bind-prop="x"></tests-twoway>');

setCustomProp('prop', 6);
_.rootElement.dispatchEvent(new Event.eventType('CustomEvent', 'change'));

expect(_.rootScope.context['x']).toEqual(6);
});
});
}

0 comments on commit 4633451

Please sign in to comment.