fix(radio): allows data-binding on value property. Closes#316

This commit is contained in:
Misko Hevery 2011-10-20 11:06:06 -07:00 committed by Igor Minar
parent fabc9f77a3
commit 7fc18b263d
3 changed files with 36 additions and 16 deletions

View file

@ -133,8 +133,8 @@ function JQLitePatchJQueryRemove(name, dispatchThis) {
} else { } else {
fireEvent = !fireEvent; fireEvent = !fireEvent;
} }
for(childIndex = 0, childLength = (children = element.children()).length; for(childIndex = 0, childLength = (children = element.children()).length;
childIndex < childLength; childIndex < childLength;
childIndex++) { childIndex++) {
list.push(jQuery(children[childIndex])); list.push(jQuery(children[childIndex]));
} }

View file

@ -546,25 +546,24 @@ angularInputType('checkbox', function(inputElement) {
</doc:example> </doc:example>
*/ */
angularInputType('radio', function(inputElement) { angularInputType('radio', function(inputElement) {
var widget = this, var widget = this;
value = inputElement.attr('value');
//correct the name //correct the name
inputElement.attr('name', widget.$id + '@' + inputElement.attr('name')); inputElement.attr('name', widget.$id + '@' + inputElement.attr('name'));
inputElement.bind('click', function() { inputElement.bind('click', function() {
widget.$apply(function() { widget.$apply(function() {
if (inputElement[0].checked) { if (inputElement[0].checked) {
widget.$emit('$viewChange', value); widget.$emit('$viewChange', widget.$value);
} }
}); });
}); });
widget.$render = function() { widget.$render = function() {
inputElement[0].checked = value == widget.$viewValue; inputElement[0].checked = isDefined(widget.$value) && (widget.$value == widget.$viewValue);
}; };
if (inputElement[0].checked) { if (inputElement[0].checked) {
widget.$viewValue = value; widget.$viewValue = widget.$value;
} }
}); });
@ -735,7 +734,7 @@ angularWidget('input', function(inputElement){
pattern = new RegExp(pattern.substr(1, pattern.length - 2)); pattern = new RegExp(pattern.substr(1, pattern.length - 2));
patternMatch = function(value) { patternMatch = function(value) {
return pattern.test(value); return pattern.test(value);
} };
} else { } else {
patternMatch = function(value) { patternMatch = function(value) {
var patternObj = modelScope.$eval(pattern); var patternObj = modelScope.$eval(pattern);
@ -743,7 +742,7 @@ angularWidget('input', function(inputElement){
throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj); throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj);
} }
return patternObj.test(value); return patternObj.test(value);
} };
} }
} }
@ -771,6 +770,7 @@ angularWidget('input', function(inputElement){
controller: TypeController, controller: TypeController,
controllerArgs: [inputElement]}); controllerArgs: [inputElement]});
watchElementProperty(this, widget, 'value', inputElement);
watchElementProperty(this, widget, 'required', inputElement); watchElementProperty(this, widget, 'required', inputElement);
watchElementProperty(this, widget, 'readonly', inputElement); watchElementProperty(this, widget, 'readonly', inputElement);
watchElementProperty(this, widget, 'disabled', inputElement); watchElementProperty(this, widget, 'disabled', inputElement);
@ -864,15 +864,17 @@ angularWidget('textarea', angularWidget('input'));
function watchElementProperty(modelScope, widget, name, element) { function watchElementProperty(modelScope, widget, name, element) {
var bindAttr = fromJson(element.attr('ng:bind-attr') || '{}'), var bindAttr = fromJson(element.attr('ng:bind-attr') || '{}'),
match = /\s*{{(.*)}}\s*/.exec(bindAttr[name]); match = /\s*{{(.*)}}\s*/.exec(bindAttr[name]),
widget['$' + name] = isBoolean = BOOLEAN_ATTR[name];
// some browsers return true some '' when required is set without value. widget['$' + name] = isBoolean
isString(element.prop(name)) || !!element.prop(name) || ? ( // some browsers return true some '' when required is set without value.
// this is needed for ie9, since it will treat boolean attributes as false isString(element.prop(name)) || !!element.prop(name) ||
!!element[0].attributes[name]; // this is needed for ie9, since it will treat boolean attributes as false
!!element[0].attributes[name])
: element.attr(name);
if (bindAttr[name] && match) { if (bindAttr[name] && match) {
modelScope.$watch(match[1], function(scope, value){ modelScope.$watch(match[1], function(scope, value){
widget['$' + name] = !!value; widget['$' + name] = isBoolean ? !!value : value;
widget.$emit('$validate'); widget.$emit('$validate');
}); });
} }

View file

@ -402,6 +402,24 @@ describe('widget: input', function() {
expect(inputs[0].checked).toBe(true); expect(inputs[0].checked).toBe(true);
expect(inputs[1].checked).toBe(false); expect(inputs[1].checked).toBe(false);
}); });
it('it should work with value attribute that is data-bound', function(){
compile(
'<li>'+
'<input ng:repeat="item in [\'a\', \'b\']" ' +
' type="radio" ng:model="choice" value="{{item}}" name="choice">'+
'</li>');
var inputs = scope.$element.find('input');
expect(inputs[0].checked).toBe(false);
expect(inputs[1].checked).toBe(false);
scope.choice = 'b';
scope.$digest();
expect(inputs[0].checked).toBe(false);
expect(inputs[1].checked).toBe(true);
});
}); });