Skip to content

Commit

Permalink
Fix error on 'validationMessage' custom binding.
Browse files Browse the repository at this point in the history
When the 'validationMessage' custom binding is used in an element, and
that element is later removed from the DOM, if the validation is
triggered an error is thrown.

This PR fixes that problem by checking on whether the element has a
parent node before updating it, and by disposing the subscription that
updates the element when the element is disposed.
  • Loading branch information
luizfar committed Jun 17, 2014
1 parent 6b9eab3 commit ab0d139
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 7 deletions.
11 changes: 11 additions & 0 deletions spec/validation-element-spec.js
Expand Up @@ -100,5 +100,16 @@ describe('Validation message element', function () {
expect(messageElement).toHaveClass('validation-message');
expect(messageElement).toHaveClass('validation-fixed');
});

it('does not throw an error when the element is removed from the dom and the validation is triggered', function () {
function removeValidationMessageElementAndValidate() {
$('#messageElement').remove();

$('#firstName').val('').trigger('change');
$('#firstName').val('Chuck').trigger('change');
}

expect(removeValidationMessageElementAndValidate).not.toThrow();
});
});
});
20 changes: 13 additions & 7 deletions src/ko-validation.js
Expand Up @@ -140,11 +140,13 @@ ko.validation.registerValidator = function (name, validatorFactory) {
};
});
ko.bindingHandlers.text.update(element, observable.validationMessage);
ko.bindingHandlers.css.update(element.parentNode, function () {
return {
'error': observable.validationState() === ko.validation.validationStates.INVALID
};
});
if (element.parentNode) {
ko.bindingHandlers.css.update(element.parentNode, function () {
return {
'error': observable.validationState() === ko.validation.validationStates.INVALID
};
});
}
}

function initValidationFor(inputElement, observable) {
Expand Down Expand Up @@ -184,8 +186,9 @@ ko.validation.registerValidator = function (name, validatorFactory) {

ko.bindingHandlers.validationMessage = {
init: function (element, valueAccessor) {
var observable = valueAccessor();
var observable, subscription;

observable = valueAccessor();
if (!ko.validation.utils.hasValidators(observable)) {
throw new Error("'validationMessage' should be used with an observable that has validation");
}
Expand All @@ -194,9 +197,12 @@ ko.validation.registerValidator = function (name, validatorFactory) {
ko.bindingHandlers.css.update(element, function () {
return { 'validation-message': true };
});
observable.validationState.subscribe(function () {
subscription = observable.validationState.subscribe(function () {
updateValidationMessage(element, observable);
});
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
subscription.dispose();
});
}
};

Expand Down

0 comments on commit ab0d139

Please sign in to comment.