Skip to content

Issue with grouped checkboxes in firefox #135

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Feb 21, 2015
122 changes: 81 additions & 41 deletions client/src/js/ng-django-forms.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,36 +141,59 @@ djng_forms_module.directive('validateMultipleFields', function() {
return {
restrict: 'A',
require: '^?form',
link: function(scope, element, attrs, controller) {
var formCtrl, subFields, checkboxElems = [];
// create child scope for changed method
scope: true,
compile: function(element, attrs) {
angular.forEach(element.find('input'), function(elem) {
elem = angular.element(elem)
elem.attr('ng-change', 'changed()');
});

return {

post: function(scope, element, attrs, controller) {
var formCtrl, subFields, checkboxCtrls = [];

function validate(event) {
var valid = false;
angular.forEach(checkboxElems, function(checkbox) {
valid = valid || checkbox.checked;
});
formCtrl.$setValidity('required', valid);
if (event && angular.isString(subFields)) {
formCtrl[subFields].$dirty = true;
formCtrl[subFields].$pristine = false;
}
}
scope.changed = function() {
validate(true)
}

if (!controller)
return;
formCtrl = controller;
try {
subFields = angular.fromJson(attrs.validateMultipleFields);
} catch (SyntaxError) {
subFields = attrs.validateMultipleFields;
}
angular.forEach(element.find('input'), function(elem) {
if (subFields.indexOf(elem.name) >= 0) {
checkboxElems.push(elem);
function validate(trigger) {
var valid = false;
angular.forEach(checkboxCtrls, function(checkbox) {
valid = valid || checkbox.$modelValue;
if(checkbox.clearRejected) {
checkbox.clearRejected();
}
});

formCtrl.$setValidity('required', valid);
formCtrl.$setValidity('rejected', true);
formCtrl.$message = ''

if (trigger && angular.isString(subFields)) {
formCtrl[subFields].$dirty = true;
formCtrl[subFields].$pristine = false;
}
}

if (!controller)
return;
formCtrl = controller;
try {
subFields = angular.fromJson(attrs.validateMultipleFields);
} catch (SyntaxError) {
subFields = attrs.validateMultipleFields;
}
angular.forEach(element.find('input'), function(elem) {
if (subFields.indexOf(elem.name) >= 0) {
checkboxCtrls.push(formCtrl[elem.name]);
}
});

validate();
}
});
element.on('change', validate);
validate();
}
}
};
});
Expand Down Expand Up @@ -241,12 +264,16 @@ djng_forms_module.factory('djangoForm', function() {
}

function resetFieldValidity(field) {
field.rejectedListenerPos = field.$viewChangeListeners.push(function() {
// changing the field the server complained about, resets the form into valid state
var pos = field.$viewChangeListeners.push(field.clearRejected = function() {
field.$message = '';
field.$setValidity('rejected', true);
field.$viewChangeListeners.splice(field.rejectedListenerPos, 1);
delete field.rejectedListenerPos;
}) - 1;
field.$viewChangeListeners.splice(pos - 1, 1);
delete field.clearRejected;
})
}

function isField(field) {
return angular.isArray(field.$viewChangeListeners)
}

return {
Expand All @@ -255,16 +282,28 @@ djng_forms_module.factory('djangoForm', function() {
setErrors: function(form, errors) {
// remove errors from this form, which may have been rejected by an earlier validation
form.$message = '';
if (form.$error.hasOwnProperty('rejected')) {
angular.forEach(form.$error.rejected, function(rejected) {
if (form.$error.hasOwnProperty('rejected') &&
angular.isArray(form.$error.rejected)) {
/*
* make copy of rejected before we loop as calling
* field.$setValidity('rejected', true) modifies the error array
* so only every other one was being removed
*/
var rejected = form.$error.rejected.concat();
angular.forEach(rejected, function(rejected) {
var field, key = rejected.$name;
if (form.hasOwnProperty(key)) {
field = form[key];
field.$message = '';
field.$setValidity('rejected', true);
if (field.rejectedListenerPos !== undefined) {
field.$viewChangeListeners.splice(field.rejectedListenerPos, 1);
delete field.rejectedListenerPos;
if (isField(field) && field.clearRejected) {
field.clearRejected();
} else {
field.$message = '';
// this field is a composite of input elements
angular.forEach(field, function(subField, subKey) {
if (subField && isField(subField) && subField.clearRejected) {
subField.clearRejected();
}
});
}
}
});
Expand All @@ -281,12 +320,12 @@ djng_forms_module.factory('djangoForm', function() {
field.$message = errors[0];
field.$setValidity('rejected', false);
field.$setPristine();
if (angular.isArray(field.$viewChangeListeners)) {
if (isField(field)) {
resetFieldValidity(field);
} else {
// this field is a composite of input elements
angular.forEach(field, function(subField, subKey) {
if (angular.isArray(subField.$viewChangeListeners)) {
if (subField && isField(subField)) {
resetFieldValidity(subField);
}
});
Expand All @@ -299,4 +338,5 @@ djng_forms_module.factory('djangoForm', function() {
};
});


})(window.angular);