Use custom attribute handler for 'value' and 'checked'.

Setting these attribute on DOM elements only affects their initial
state. Instead, one should set the JavaScript property on the
DOM element directly.

Fixes #1752
This commit is contained in:
Avital Oliver
2014-01-14 19:29:55 -08:00
parent 06c0a9d8aa
commit da2a17f80d
2 changed files with 44 additions and 4 deletions

View File

@@ -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.
};

View File

@@ -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') {