If you add any of the angular directives for validation (ng-minlength, ng-maxlength, ng-pattern, etc.) to an input that is bound to a breeze entity it blocks any user input if f
https://docs.angularjs.org/error/ngModel/numfmt describes how Angular considers it a programming error, not a user input error, if programmatic model changes don't respect the input's validation rules.
If your model does not contain actual numbers then it is up to the application developer to use a directive that will do the conversion in the ngModel $formatters and $parsers pipeline.
Their example describes a String
model value for an <input type='number'>
but the same logic applies here, I think. If your input contains a minLength attribute, the scope should not get updated with strings that are too short.
So to fix it, add a custom directive to your input that pushes a custom parser into the $parsers
pipeline.
For instance, the following directive will hold off writing the value of an <input type='text' minLength='4' min4>
to the scope until a long enough string has been typed into it:
.directive('min4', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
ngModel.$parsers.push(function(value) {
return value && value.length >= 4 ? value : "";
});
}
};
});
This prevents the nasty interactions that otherwise occur when Breeze writes updated values back to the scope and ends up overwriting not-yet-legal state in the input.
See Plunker demo
I'm happy to look at your plunker and see if there is something Breeze can do about this.
I'm not terribly surprised. Ng also struggles when you combine it with HTML 5 validation as I recall. You really should only use one scheme I think.
Do you disagree?
Also, have you considered the zValidate directive in the Breeze Labs breeze.directives.js? We think that is the best way to expose Breeze entity property validation errors in the view.
Another solution to consider is to use the ng-model-options attribute made available with Angular 1.3+.
In this way, you can prevent the Angular digest occurring after every keypress, and instead defer it to, for example, the 'blur' event so that the use has a chance to actually enter the valid data.
It would look like this:
<input type="email" ng-model="customer.email" ng-model-options="{ updateOn: 'blur' }">
However, this still has the limitation that if you enter invalid input, on blur the input will be cleared out and the use will have to enter it all again. Not very user friendly in my opinion, so I'll be trying out the breeze-only approach to circumvent this issue.
However, I thought this solution was also worth mentioning here.
Angular 1.3.0-rc.1 introduced the allowInvalid
option for use with the ngModelOptions
directive. It is essentially a formalization of the OP's hack at line 16331. The option instructs Angular to allow invalid form inputs to be written to $scope, and solves the problem neatly.
Usage:
<input type="email" ng-model-options="{allowInvalid: true}" ng-model="my_breeze_model.email"/>
See this feature request for more information: https://github.com/angular/angular.js/issues/8290.