С помощью Angular директив проверки с Breeze блокирует любой ввод, который недействителен
Если вы добавите какую-либо из директив angular для проверки (ng-minlength, ng-maxlength, ng-pattern и т.д.) на вход, привязанный к ветру, он блокирует любой пользовательский ввод, если он найден недействителен.
Если значение из ng-model изначально корректно, оно отображается, но если вы измените значение на что-то недействительное, поле ввода будет очищено, то для модели будет установлено значение null, и вы не сможете ввести все, что может быть изначально инвалид. Однако, если вы скопируете действительное значение в поле, которое оно показывает.
Мне было бы хорошо, если значение модели было установлено равным null, если оно недействительно, если оно не очистило вход, а затем предотвратило изменения.
Также у меня возникает ощущение, что все, что вызывает эту проблему, также испортит u-mask. То же самое происходит и без директив angular.
вот Plunker, который я нашел по аналогичному вопросу, который я изменил, чтобы показать свою проблему:
http://plnkr.co/edit/dVsF7GFY65a30soLL5W8?p=preview
Edit
После многих часов исследований я нашел решение, которое работает, хотя я не уверен в каких-либо побочных эффектах.
Это связано с тем, как angular выполняет валидацию в первую очередь, устанавливая значение $modelValue в 'undefined', если он не удаляет какие-либо валидаторы, поскольку он делает это через $parsers и $formatters.
Я нашел этот код в angular (строка 16331), который вызывается каждым валидатором angular:
function validate(ctrl, validatorName, validity, value){
ctrl.$setValidity(validatorName, validity);
return validity ? value : undefined;
}
Я изменил его, чтобы вернуть 'значение' вместо 'undefined':
function validate(ctrl, validatorName, validity, value){
ctrl.$setValidity(validatorName, validity);
return value;
}
Angular все еще корректно устанавливает правильность. Хотя я уверен, что это не лучшее решение или даже хорошее.
Я подозреваю, что проблема возникает, когда angular устанавливает $modelValue в 'undefined', тогда Breeze видит, что модель изменилась и обновляет объект, который затем обновляет модель, которая затем очищает ввод и т.д.... Или что-то вроде этого...
Я нашел, что это полезно в моих поисках. Возможно, это будет полезно для одного из вас, который знает гораздо больше, чем я https://github.com/angular/angular.js/issues/1412
Ответы
Ответ 1
Angular 1.3.0-rc.1 представил параметр allowInvalid
для использования с директивой ngModelOptions
. Это, по сути, формализация взлома OP в строке 16331. Опция сообщает Angular разрешить ввод недопустимых входных данных формы в область $scope и решает проблему аккуратно.
Использование:
<input type="email" ng-model-options="{allowInvalid: true}" ng-model="my_breeze_model.email"/>
См. этот запрос функции для получения дополнительной информации: https://github.com/angular/angular.js/issues/8290.
Ответ 2
Я рад посмотреть на ваш плункер и посмотреть, есть ли что-то, что может сделать Бриз.
Я не очень удивлен. Ng также борется, когда вы совмещаете его с проверкой HTML 5, насколько я помню. Вы действительно должны использовать только одну схему, я думаю.
Вы не согласны?
Кроме того, рассмотрели ли вы директиву zValidate в Breeze Labs breeze.directives.js? Мы считаем, что это лучший способ разоблачить ошибки проверки подлинности объекта Breeze в представлении.
Ответ 3
Еще одно решение - использовать атрибут ng-model-options
, доступный с помощью Angular 1.3 +.
Таким образом, вы можете предотвратить дайджест Angular, возникающий после каждого нажатия клавиши, и вместо этого отложить его, например, на событие "размытие", чтобы у использования была возможность фактически ввести действительные данные.
Это будет выглядеть так:
<input type="email" ng-model="customer.email" ng-model-options="{ updateOn: 'blur' }">
Тем не менее, это все еще имеет ограничение на то, что если вы введете недопустимый ввод, при размытии вход будет очищен, и использование снова должно будет ввести его снова. На мой взгляд, это не очень удобно для пользователя, поэтому я буду пытаться использовать только один ветерок, чтобы обойти эту проблему.
Однако, я думал, что это решение также стоит упомянуть здесь.
Ответ 4
https://docs.angularjs.org/error/ngModel/numfmt описывает, как Angular считает ошибку программирования, а не ошибкой ввода пользователя, если изменения в программной модели не уважают правила проверки ввода.
Если ваша модель не содержит фактических номеров, то разработчик приложения может использовать директиву, которая будет выполнять преобразование в конвейере ngModel $formatters и $parsers.
В их примере описывается значение модели String
для <input type='number'>
, но, я думаю, здесь применяется одна и та же логика. Если ваш вход содержит атрибут minLength, область не должна обновляться с слишком короткими строками.
Итак, чтобы исправить это, добавьте в свой файл настраиваемую директиву, которая подталкивает пользовательский парсер в конвейер $parsers
.
Например, следующая директива не будет записывать значение <input type='text' minLength='4' min4>
в область действия до тех пор, пока в нее не будет введена достаточно длинная строка:
.directive('min4', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
ngModel.$parsers.push(function(value) {
return value && value.length >= 4 ? value : "";
});
}
};
});
Это предотвращает неприятные взаимодействия, которые в противном случае возникают, когда Breeze записывает обновленные значения обратно в область действия и заканчивает перезаписывание еще не законного состояния на входе.
См. Демо-версия Plunker