-
Notifications
You must be signed in to change notification settings - Fork 77
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
Does not work with ngSwitch inside ngRepeat #25
Comments
I had a similar problem (with |
Thanks @VanTanev, your version seems to be working in our case as well! |
I'm having the same issues. I will take a look at @VanTanev version, thanks |
@gommo I just went back to my code and updated it a little. In a real project, it turns out that you often times need to put multiple This update makes the directive detect errors on multiple elements: http://plnkr.co/edit/a6XWR657EpTOW2JL7bhM?p=preview And now, for some extra. In my projects, I do backend validation on all forms. Sometimes, there are validations that only the backend can do. In this case, I need to mark a var user = {
"username": "VanTanev",
"password": "123",
"errors": {
"username": ["username is already in use"]
}
} So, in order to make the <!-- the important part --> <div show-errors="user"> <!-- the important part -->
<input type="text" name="username" class="form-control" ng-model="user.username" />
<input type="text" name="password" class="form-control" ng-model="user.password" />
</div> and modified the watch functuon in the directive: $scope.$watch(function() {
// on scope changes, check if the input's validation status has changed.
// additionally, if an input has not been touched or the form has not been
// yet submitted, consider the element valid
var hasFormError = ngFormCtrl[childInputName].$invalid
&& (ngFormCtrl[childInputName].$touched || ngFormCtrl[childInputName].$dirty || ngFormCtrl.$submitted);
// additionally check the model for errors on this field
var hasModelError = !!($attrs['showErrors'] && $scope.$eval($attrs['showErrors'] + '.errors["' + childInputName + '"].length'));
return hasFormError || hasModelError;
}, function(is_invalid) {
$element.toggleClass('has-error', is_invalid);
}); Basically, I give the model object's name to the |
Great work ! @VanTanev Do you wanna put it on your github ? |
So basically the real magic here is the timeout right? I came here because I had a similar issue where the show-errors didnt see an input generated several levels of components/directives deep down my DOM nest. |
@VictorioBerra For the most part, yes. This is the current version that I use in my projects: https://gist.github.com/VanTanev/724cef9f2950cb2b246e33bd407187e0 import _ from 'lodash'
/* @ngInject */
export default function highlightErrorsDirective($timeout) {
var directive = {
restrict: 'A',
require: '^form',
link: highlightErrorsLinkFn,
};
return directive;
////////////////////////
function highlightErrorsLinkFn(scope, element, attr, ngFormCtrl) {
// This timeout is necessary to handle the case when we have
// ng generated code inside of the highlight-errors element.
// We want to allow interpolation of child elements, so we just
// offset the attachment of the watchers until the browser renders
// the next frame, by using a $timeout(func, 0, false)
let promise = $timeout(function() {
// we search for .form-control where the name attriubte is set
var childInputs = element[0].querySelectorAll('.form-control[name]');
// and add watchers for all elements
_.each(childInputs, function(childInput) {
var childInputName = childInput && childInput.getAttribute('name');
if (!childInputName || angular.isUndefined(ngFormCtrl[childInputName])) {
// if we cannot find the expected element, throw an error and
// halt compilation
throw new Error(`highlightErrors directive requires that you have
a child ".form-control" element with a "name" attribute.`);
}
scope.$watch(function() {
// on scope changes, check if the input's validation status has changed.
// additionally, if an input has not been touched or the form has not been
// yet submitted, consider the element valid
var hasFormError = ngFormCtrl[childInputName].$invalid &&
(ngFormCtrl[childInputName].$touched ||
ngFormCtrl[childInputName].$dirty ||
ngFormCtrl.$submitted);
var hasModelError = false;
if (attr.highlightErrors) {
hasModelError = !!scope.$eval(
`${attr.highlightErrors}.errors["${childInputName}"].length`
);
}
return hasFormError || hasModelError;
}, function(hasError) {
element.toggleClass('has-error', hasError);
});
});
}, 0, false);
scope.$on('$destroy', () => $timeout.cancel(promise))
}
} All the best :) |
@VanTanev I hope im not asking too much, but could you create a repo for this and add a license? maybe MIT? That way we can all contribute and use this in projects at work, etc. |
I will add the MIT license to the gist, and see about making a dedicated repo; Would need to setup tests, builds, docs, etc etc etc for that. |
I tried using the fix from #16, but unfortunately it doesn't work for me. What I have is something that looks like:
This results in the error:
show-errors element has no child input elements with a 'name' attribute and a 'form-control' class
However, if I change the code to:
Everything works as expected.
The text was updated successfully, but these errors were encountered: