mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-05-09 07:14:44 +00:00
fixed issue with radio view clobering model if radio was checked.
This commit is contained in:
parent
0a288d1db3
commit
22d1464d7a
4 changed files with 176 additions and 129 deletions
|
|
@ -97,7 +97,7 @@ function createScope(parent, services, existing) {
|
||||||
$set: bind(instance, setter, instance),
|
$set: bind(instance, setter, instance),
|
||||||
|
|
||||||
$eval: function $eval(exp) {
|
$eval: function $eval(exp) {
|
||||||
if (exp) {
|
if (exp !== undefined) {
|
||||||
return expressionCompile(exp).apply(instance, slice.call(arguments, 1, arguments.length));
|
return expressionCompile(exp).apply(instance, slice.call(arguments, 1, arguments.length));
|
||||||
} else {
|
} else {
|
||||||
foreach(evalLists.sorted, function(list) {
|
foreach(evalLists.sorted, function(list) {
|
||||||
|
|
|
||||||
|
|
@ -155,9 +155,15 @@ function initWidgetValue(initValue) {
|
||||||
|
|
||||||
function radioInit(model, view, element) {
|
function radioInit(model, view, element) {
|
||||||
var modelValue = model.get(), viewValue = view.get(), input = element[0];
|
var modelValue = model.get(), viewValue = view.get(), input = element[0];
|
||||||
|
input.checked = false;
|
||||||
input.name = this.$id + '@' + input.name;
|
input.name = this.$id + '@' + input.name;
|
||||||
if (isUndefined(modelValue)) model.set(null);
|
if (isUndefined(modelValue)) {
|
||||||
if (viewValue !== null) model.set(viewValue);
|
model.set(modelValue = null);
|
||||||
|
}
|
||||||
|
if (modelValue == null && viewValue !== null) {
|
||||||
|
model.set(viewValue);
|
||||||
|
}
|
||||||
|
view.set(modelValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
function inputWidget(events, modelAccessor, viewAccessor, initFn) {
|
function inputWidget(events, modelAccessor, viewAccessor, initFn) {
|
||||||
|
|
|
||||||
|
|
@ -15,133 +15,146 @@ describe('scope/model', function(){
|
||||||
expect(model.$root).toEqual(model);
|
expect(model.$root).toEqual(model);
|
||||||
});
|
});
|
||||||
|
|
||||||
//$eval
|
describe('$eval', function(){
|
||||||
it('should eval function with correct this and pass arguments', function(){
|
it('should eval function with correct this and pass arguments', function(){
|
||||||
var model = createScope();
|
var model = createScope();
|
||||||
model.$eval(function(name){
|
model.$eval(function(name){
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}, 'works');
|
}, 'works');
|
||||||
expect(model.name).toEqual('works');
|
expect(model.name).toEqual('works');
|
||||||
});
|
|
||||||
|
|
||||||
it('should eval expression with correct this', function(){
|
|
||||||
var model = createScope();
|
|
||||||
model.$eval('name="works"');
|
|
||||||
expect(model.name).toEqual('works');
|
|
||||||
});
|
|
||||||
|
|
||||||
//$watch
|
|
||||||
it('should watch an expression for change', function(){
|
|
||||||
var model = createScope();
|
|
||||||
model.oldValue = "";
|
|
||||||
var nameCount = 0, evalCount = 0;
|
|
||||||
model.name = 'adam';
|
|
||||||
model.$watch('name', function(){ nameCount ++; });
|
|
||||||
model.$watch(function(){return model.name;}, function(newValue, oldValue){
|
|
||||||
this.newValue = newValue;
|
|
||||||
this.oldValue = oldValue;
|
|
||||||
});
|
});
|
||||||
model.$onEval(function(){evalCount ++;});
|
|
||||||
model.name = 'misko';
|
|
||||||
model.$eval();
|
|
||||||
expect(nameCount).toEqual(2);
|
|
||||||
expect(evalCount).toEqual(1);
|
|
||||||
expect(model.newValue).toEqual('misko');
|
|
||||||
expect(model.oldValue).toEqual('adam');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should eval with no arguments', function(){
|
it('should eval expression with correct this', function(){
|
||||||
var model = createScope();
|
var model = createScope();
|
||||||
var count = 0;
|
model.$eval('name="works"');
|
||||||
model.$onEval(function(){count++;});
|
expect(model.name).toEqual('works');
|
||||||
model.$eval();
|
});
|
||||||
expect(count).toEqual(1);
|
|
||||||
});
|
it('should do nothing on empty string and not update view', function(){
|
||||||
|
var model = createScope();
|
||||||
//$bind
|
var onEval = jasmine.createSpy('onEval');
|
||||||
it('should curry a function with respect to scope', function(){
|
model.$onEval(onEval);
|
||||||
var model = createScope();
|
model.$eval('');
|
||||||
model.name = 'misko';
|
expect(onEval).wasNotCalled();
|
||||||
expect(model.$bind(function(){return this.name;})()).toEqual('misko');
|
|
||||||
});
|
|
||||||
|
|
||||||
//$tryEval
|
|
||||||
it('should report error on element', function(){
|
|
||||||
var scope = createScope();
|
|
||||||
scope.$tryEval('throw "myerror";', function(error){
|
|
||||||
scope.error = error;
|
|
||||||
});
|
});
|
||||||
expect(scope.error).toEqual('myerror');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should report error on visible element', function(){
|
describe('$watch', function(){
|
||||||
var element = jqLite('<div></div>');
|
it('should watch an expression for change', function(){
|
||||||
var scope = createScope();
|
var model = createScope();
|
||||||
scope.$tryEval('throw "myError"', element);
|
model.oldValue = "";
|
||||||
expect(element.attr('ng-exception')).toEqual('"myError"'); // errors are jsonified
|
var nameCount = 0, evalCount = 0;
|
||||||
expect(element.hasClass('ng-exception')).toBeTruthy();
|
model.name = 'adam';
|
||||||
|
model.$watch('name', function(){ nameCount ++; });
|
||||||
|
model.$watch(function(){return model.name;}, function(newValue, oldValue){
|
||||||
|
this.newValue = newValue;
|
||||||
|
this.oldValue = oldValue;
|
||||||
|
});
|
||||||
|
model.$onEval(function(){evalCount ++;});
|
||||||
|
model.name = 'misko';
|
||||||
|
model.$eval();
|
||||||
|
expect(nameCount).toEqual(2);
|
||||||
|
expect(evalCount).toEqual(1);
|
||||||
|
expect(model.newValue).toEqual('misko');
|
||||||
|
expect(model.oldValue).toEqual('adam');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should eval with no arguments', function(){
|
||||||
|
var model = createScope();
|
||||||
|
var count = 0;
|
||||||
|
model.$onEval(function(){count++;});
|
||||||
|
model.$eval();
|
||||||
|
expect(count).toEqual(1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should report error on $excetionHandler', function(){
|
describe('$bind', function(){
|
||||||
var element = jqLite('<div></div>');
|
it('should curry a function with respect to scope', function(){
|
||||||
var scope = createScope();
|
var model = createScope();
|
||||||
scope.$exceptionHandler = function(e){
|
model.name = 'misko';
|
||||||
this.error = e;
|
expect(model.$bind(function(){return this.name;})()).toEqual('misko');
|
||||||
};
|
});
|
||||||
scope.$tryEval('throw "myError"');
|
});
|
||||||
expect(scope.error).toEqual("myError");
|
|
||||||
|
describe('$tryEval', function(){
|
||||||
|
it('should report error on element', function(){
|
||||||
|
var scope = createScope();
|
||||||
|
scope.$tryEval('throw "myerror";', function(error){
|
||||||
|
scope.error = error;
|
||||||
|
});
|
||||||
|
expect(scope.error).toEqual('myerror');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should report error on visible element', function(){
|
||||||
|
var element = jqLite('<div></div>');
|
||||||
|
var scope = createScope();
|
||||||
|
scope.$tryEval('throw "myError"', element);
|
||||||
|
expect(element.attr('ng-exception')).toEqual('"myError"'); // errors are jsonified
|
||||||
|
expect(element.hasClass('ng-exception')).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should report error on $excetionHandler', function(){
|
||||||
|
var element = jqLite('<div></div>');
|
||||||
|
var scope = createScope();
|
||||||
|
scope.$exceptionHandler = function(e){
|
||||||
|
this.error = e;
|
||||||
|
};
|
||||||
|
scope.$tryEval('throw "myError"');
|
||||||
|
expect(scope.error).toEqual("myError");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// $onEval
|
// $onEval
|
||||||
|
describe('$onEval', function(){
|
||||||
|
it("should eval using priority", function(){
|
||||||
|
var scope = createScope();
|
||||||
|
scope.log = "";
|
||||||
|
scope.$onEval('log = log + "middle;"');
|
||||||
|
scope.$onEval(-1, 'log = log + "first;"');
|
||||||
|
scope.$onEval(1, 'log = log + "last;"');
|
||||||
|
scope.$eval();
|
||||||
|
expect(scope.log).toEqual('first;middle;last;');
|
||||||
|
});
|
||||||
|
|
||||||
it("should eval using priority", function(){
|
it("should have $root and $parent", function(){
|
||||||
var scope = createScope();
|
var parent = createScope();
|
||||||
scope.log = "";
|
var scope = createScope(parent);
|
||||||
scope.$onEval('log = log + "middle;"');
|
expect(scope.$root).toEqual(parent);
|
||||||
scope.$onEval(-1, 'log = log + "first;"');
|
expect(scope.$parent).toEqual(parent);
|
||||||
scope.$onEval(1, 'log = log + "last;"');
|
});
|
||||||
scope.$eval();
|
|
||||||
expect(scope.log).toEqual('first;middle;last;');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should have $root and $parent", function(){
|
describe('service injection', function(){
|
||||||
var parent = createScope();
|
it('should inject services', function(){
|
||||||
var scope = createScope(parent);
|
var scope = createScope(null, {
|
||||||
expect(scope.$root).toEqual(parent);
|
service:function(){
|
||||||
expect(scope.$parent).toEqual(parent);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Service injection
|
|
||||||
it('should inject services', function(){
|
|
||||||
var scope = createScope(null, {
|
|
||||||
service:function(){
|
|
||||||
return "ABC";
|
return "ABC";
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
expect(scope.service).toEqual("ABC");
|
||||||
});
|
});
|
||||||
expect(scope.service).toEqual("ABC");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should inject arugments', function(){
|
it('should inject arugments', function(){
|
||||||
var scope = createScope(null, {
|
var scope = createScope(null, {
|
||||||
name:function(){
|
name:function(){
|
||||||
return "misko";
|
return "misko";
|
||||||
},
|
},
|
||||||
greet: extend(function(name) {
|
greet: extend(function(name) {
|
||||||
return 'hello ' + name;
|
return 'hello ' + name;
|
||||||
}, {inject:['name']})
|
}, {inject:['name']})
|
||||||
});
|
|
||||||
expect(scope.greet).toEqual("hello misko");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw error on missing dependency', function(){
|
|
||||||
try {
|
|
||||||
createScope(null, {
|
|
||||||
greet: extend(function(name) {
|
|
||||||
}, {inject:['name']})
|
|
||||||
});
|
});
|
||||||
} catch(e) {
|
expect(scope.greet).toEqual("hello misko");
|
||||||
expect(e).toEqual("Don't know how to inject 'name'.");
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
it('should throw error on missing dependency', function(){
|
||||||
|
try {
|
||||||
|
createScope(null, {
|
||||||
|
greet: extend(function(name) {
|
||||||
|
}, {inject:['name']})
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
expect(e).toEqual("Don't know how to inject 'name'.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ describe("widget", function(){
|
||||||
compile = function(html, before) {
|
compile = function(html, before) {
|
||||||
element = jqLite(html);
|
element = jqLite(html);
|
||||||
scope = compiler.compile(element)(element);
|
scope = compiler.compile(element)(element);
|
||||||
(before||noop)();
|
(before||noop).apply(scope);
|
||||||
scope.$init();
|
scope.$init();
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
@ -222,29 +222,57 @@ describe("widget", function(){
|
||||||
expect(scope.checkbox).toEqual(true);
|
expect(scope.checkbox).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support type="radio"', function(){
|
describe('radio', function(){
|
||||||
compile('<div>' +
|
|
||||||
'<input type="radio" name="chose" value="A" ng-change="clicked = 1"/>' +
|
it('should support type="radio"', function(){
|
||||||
'<input type="radio" name="chose" value="B" checked ng-change="clicked = 2"/>' +
|
compile('<div>' +
|
||||||
'<input type="radio" name="chose" value="C" ng-change="clicked = 3"/>' +
|
'<input type="radio" name="chose" value="A" ng-change="clicked = 1"/>' +
|
||||||
|
'<input type="radio" name="chose" value="B" checked ng-change="clicked = 2"/>' +
|
||||||
|
'<input type="radio" name="chose" value="C" ng-change="clicked = 3"/>' +
|
||||||
'</div>');
|
'</div>');
|
||||||
var a = element[0].childNodes[0];
|
var a = element[0].childNodes[0];
|
||||||
var b = element[0].childNodes[1];
|
var b = element[0].childNodes[1];
|
||||||
expect(b.name.split('@')[1]).toEqual('chose');
|
expect(b.name.split('@')[1]).toEqual('chose');
|
||||||
expect(scope.chose).toEqual('B');
|
expect(scope.chose).toEqual('B');
|
||||||
scope.chose = 'A';
|
scope.chose = 'A';
|
||||||
scope.$eval();
|
scope.$eval();
|
||||||
expect(a.checked).toEqual(true);
|
expect(a.checked).toEqual(true);
|
||||||
|
|
||||||
scope.chose = 'B';
|
scope.chose = 'B';
|
||||||
scope.$eval();
|
scope.$eval();
|
||||||
expect(a.checked).toEqual(false);
|
expect(a.checked).toEqual(false);
|
||||||
expect(b.checked).toEqual(true);
|
expect(b.checked).toEqual(true);
|
||||||
expect(scope.clicked).not.toBeDefined();
|
expect(scope.clicked).not.toBeDefined();
|
||||||
|
|
||||||
|
click(a);
|
||||||
|
expect(scope.chose).toEqual('A');
|
||||||
|
expect(scope.clicked).toEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should honor model over html checked keyword after', function(){
|
||||||
|
compile('<div>' +
|
||||||
|
'<input type="radio" name="choose" value="A""/>' +
|
||||||
|
'<input type="radio" name="choose" value="B" checked/>' +
|
||||||
|
'<input type="radio" name="choose" value="C"/>' +
|
||||||
|
'</div>', function(){
|
||||||
|
this.choose = 'C';
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(scope.choose).toEqual('C');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should honor model over html checked keyword before', function(){
|
||||||
|
compile('<div>' +
|
||||||
|
'<input type="radio" name="choose" value="A""/>' +
|
||||||
|
'<input type="radio" name="choose" value="B" checked/>' +
|
||||||
|
'<input type="radio" name="choose" value="C"/>' +
|
||||||
|
'</div>', function(){
|
||||||
|
this.choose = 'A';
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(scope.choose).toEqual('A');
|
||||||
|
});
|
||||||
|
|
||||||
click(a);
|
|
||||||
expect(scope.chose).toEqual('A');
|
|
||||||
expect(scope.clicked).toEqual(1);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support type="select-one"', function(){
|
it('should support type="select-one"', function(){
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue