mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-17 07:40:22 +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),
|
||||
|
||||
$eval: function $eval(exp) {
|
||||
if (exp) {
|
||||
if (exp !== undefined) {
|
||||
return expressionCompile(exp).apply(instance, slice.call(arguments, 1, arguments.length));
|
||||
} else {
|
||||
foreach(evalLists.sorted, function(list) {
|
||||
|
|
|
|||
|
|
@ -155,9 +155,15 @@ function initWidgetValue(initValue) {
|
|||
|
||||
function radioInit(model, view, element) {
|
||||
var modelValue = model.get(), viewValue = view.get(), input = element[0];
|
||||
input.checked = false;
|
||||
input.name = this.$id + '@' + input.name;
|
||||
if (isUndefined(modelValue)) model.set(null);
|
||||
if (viewValue !== null) model.set(viewValue);
|
||||
if (isUndefined(modelValue)) {
|
||||
model.set(modelValue = null);
|
||||
}
|
||||
if (modelValue == null && viewValue !== null) {
|
||||
model.set(viewValue);
|
||||
}
|
||||
view.set(modelValue);
|
||||
}
|
||||
|
||||
function inputWidget(events, modelAccessor, viewAccessor, initFn) {
|
||||
|
|
|
|||
|
|
@ -15,133 +15,146 @@ describe('scope/model', function(){
|
|||
expect(model.$root).toEqual(model);
|
||||
});
|
||||
|
||||
//$eval
|
||||
it('should eval function with correct this and pass arguments', function(){
|
||||
var model = createScope();
|
||||
model.$eval(function(name){
|
||||
this.name = name;
|
||||
}, '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;
|
||||
describe('$eval', function(){
|
||||
it('should eval function with correct this and pass arguments', function(){
|
||||
var model = createScope();
|
||||
model.$eval(function(name){
|
||||
this.name = name;
|
||||
}, 'works');
|
||||
expect(model.name).toEqual('works');
|
||||
});
|
||||
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);
|
||||
});
|
||||
|
||||
//$bind
|
||||
it('should curry a function with respect to scope', function(){
|
||||
var model = createScope();
|
||||
model.name = 'misko';
|
||||
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;
|
||||
it('should eval expression with correct this', function(){
|
||||
var model = createScope();
|
||||
model.$eval('name="works"');
|
||||
expect(model.name).toEqual('works');
|
||||
});
|
||||
|
||||
it('should do nothing on empty string and not update view', function(){
|
||||
var model = createScope();
|
||||
var onEval = jasmine.createSpy('onEval');
|
||||
model.$onEval(onEval);
|
||||
model.$eval('');
|
||||
expect(onEval).wasNotCalled();
|
||||
});
|
||||
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();
|
||||
describe('$watch', function(){
|
||||
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(){
|
||||
var model = createScope();
|
||||
var count = 0;
|
||||
model.$onEval(function(){count++;});
|
||||
model.$eval();
|
||||
expect(count).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
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");
|
||||
describe('$bind', function(){
|
||||
it('should curry a function with respect to scope', function(){
|
||||
var model = createScope();
|
||||
model.name = 'misko';
|
||||
expect(model.$bind(function(){return this.name;})()).toEqual('misko');
|
||||
});
|
||||
});
|
||||
|
||||
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
|
||||
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(){
|
||||
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 have $root and $parent", function(){
|
||||
var parent = createScope();
|
||||
var scope = createScope(parent);
|
||||
expect(scope.$root).toEqual(parent);
|
||||
expect(scope.$parent).toEqual(parent);
|
||||
});
|
||||
});
|
||||
|
||||
it("should have $root and $parent", function(){
|
||||
var parent = createScope();
|
||||
var scope = createScope(parent);
|
||||
expect(scope.$root).toEqual(parent);
|
||||
expect(scope.$parent).toEqual(parent);
|
||||
});
|
||||
|
||||
// Service injection
|
||||
it('should inject services', function(){
|
||||
var scope = createScope(null, {
|
||||
service:function(){
|
||||
describe('service injection', function(){
|
||||
it('should inject services', function(){
|
||||
var scope = createScope(null, {
|
||||
service:function(){
|
||||
return "ABC";
|
||||
}
|
||||
});
|
||||
expect(scope.service).toEqual("ABC");
|
||||
});
|
||||
expect(scope.service).toEqual("ABC");
|
||||
});
|
||||
|
||||
it('should inject arugments', function(){
|
||||
var scope = createScope(null, {
|
||||
name:function(){
|
||||
it('should inject arugments', function(){
|
||||
var scope = createScope(null, {
|
||||
name:function(){
|
||||
return "misko";
|
||||
},
|
||||
greet: extend(function(name) {
|
||||
return 'hello ' + 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(e).toEqual("Don't know how to 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(e).toEqual("Don't know how to inject 'name'.");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ describe("widget", function(){
|
|||
compile = function(html, before) {
|
||||
element = jqLite(html);
|
||||
scope = compiler.compile(element)(element);
|
||||
(before||noop)();
|
||||
(before||noop).apply(scope);
|
||||
scope.$init();
|
||||
};
|
||||
});
|
||||
|
|
@ -222,29 +222,57 @@ describe("widget", function(){
|
|||
expect(scope.checkbox).toEqual(true);
|
||||
});
|
||||
|
||||
it('should support type="radio"', function(){
|
||||
compile('<div>' +
|
||||
'<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"/>' +
|
||||
describe('radio', function(){
|
||||
|
||||
it('should support type="radio"', function(){
|
||||
compile('<div>' +
|
||||
'<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>');
|
||||
var a = element[0].childNodes[0];
|
||||
var b = element[0].childNodes[1];
|
||||
expect(b.name.split('@')[1]).toEqual('chose');
|
||||
expect(scope.chose).toEqual('B');
|
||||
scope.chose = 'A';
|
||||
scope.$eval();
|
||||
expect(a.checked).toEqual(true);
|
||||
var a = element[0].childNodes[0];
|
||||
var b = element[0].childNodes[1];
|
||||
expect(b.name.split('@')[1]).toEqual('chose');
|
||||
expect(scope.chose).toEqual('B');
|
||||
scope.chose = 'A';
|
||||
scope.$eval();
|
||||
expect(a.checked).toEqual(true);
|
||||
|
||||
scope.chose = 'B';
|
||||
scope.$eval();
|
||||
expect(a.checked).toEqual(false);
|
||||
expect(b.checked).toEqual(true);
|
||||
expect(scope.clicked).not.toBeDefined();
|
||||
scope.chose = 'B';
|
||||
scope.$eval();
|
||||
expect(a.checked).toEqual(false);
|
||||
expect(b.checked).toEqual(true);
|
||||
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(){
|
||||
|
|
|
|||
Loading…
Reference in a new issue