diff --git a/packages/ui/attrs.js b/packages/ui/attrs.js index 01be4cee70..af25cd1667 100644 --- a/packages/ui/attrs.js +++ b/packages/ui/attrs.js @@ -121,19 +121,25 @@ var isSVGElement = function (elem) { // XXX make it possible for users to register attribute handlers! makeAttributeHandler = function (elem, name, value) { - // XXX will need one for 'style' on IE, though modern browsers - // seem to handle setAttribute ok. + // generally, use setAttribute but certain attributes need to be set + // by directly setting a JavaScript property on the DOM element. if (name === 'class') { if (isSVGElement(elem)) { return new SVGClassHandler(name, value); } else { return new ClassHandler(name, value); } - } else if (name === 'selected') { + } else if (name === 'selected' || name === 'checked') { return new BooleanHandler(name, value); - } else if (elem.tagName === 'TEXTAREA' && name === 'value') { + } else if ((elem.tagName === 'TEXTAREA' || elem.tagName === 'INPUT') + && name === 'value') { + // internally, TEXTAREAs tracks their value in the 'value' + // attribute just like INPUTs. return new ValueHandler(name, value); } else { return new AttributeHandler(name, value); } + + // XXX will need one for 'style' on IE, though modern browsers + // seem to handle setAttribute ok. }; diff --git a/packages/ui/render_tests.js b/packages/ui/render_tests.js index 1622763135..9663cfc97f 100644 --- a/packages/ui/render_tests.js +++ b/packages/ui/render_tests.js @@ -13,6 +13,7 @@ var LI = HTML.LI; var SPAN = HTML.SPAN; var HR = HTML.HR; var TEXTAREA = HTML.TEXTAREA; +var INPUT = HTML.INPUT; Tinytest.add("ui - render - basic", function (test) { var run = function (input, expectedInnerHTML, expectedHTML, expectedCode) { @@ -74,6 +75,39 @@ Tinytest.add("ui - render - basic", function (test) { }); +// test that we correctly update the 'value' property on input fields +// rather than the 'value' attribute. the 'value' attribute only sets +// the initial value. +Tinytest.add("ui - render - input - value", function (test) { + var R = ReactiveVar("hello"); + var div = document.createElement("DIV"); + materialize(INPUT({value: function () { return R.get(); }}), div); + var inputEl = div.querySelector('input'); + test.equal(inputEl.value, "hello"); + inputEl.value = "goodbye"; + R.set("hola"); + Deps.flush(); + test.equal(inputEl.value, "hola"); +}); + +// test that we correctly update the 'checked' property rather than +// the 'checked' attribute on input fields of type 'checkbox'. the +// 'checked' attribute only sets the initial value. +Tinytest.add("ui - render - input - checked", function (test) { + var R = ReactiveVar(null); + var div = document.createElement("DIV"); + materialize(INPUT({type: "checkbox", checked: function () { return R.get(); }}), div); + var inputEl = div.querySelector('input'); + test.equal(inputEl.checked, false); + inputEl.checked = true; + + R.set("checked"); + Deps.flush(); + R.set(null); + Deps.flush(); + test.equal(inputEl.checked, false); +}); + Tinytest.add("ui - render - textarea", function (test) { var run = function (optNode, text, html, code) { if (typeof optNode === 'string') {