Пользовательская форма проверки валидации для сравнения двух полей
Я новичок angular, и я наткнулся на что-то в том, как работают директивы валидации формы angular.
Я знаю, что я могу довольно легко добавлять директивы в отдельные поля, но я пытаюсь добавить проверку, которая будет сравнивать два поля формы (оба из которых являются элементами модели).
Здесь скелет формы:
<form name="edit_form" >
<input name="min" type="number" ng-model="field.min"/>
<input name="max" type="number" ng-model="field.max"/>
</form>
<div class="error" ng-show="edit_form.min.$dirty || edit_form.max.$dirty">
<small class="error" ng-show="(what goes here?)">
Min cannot exceed max
</small>
</div>
Короче говоря, я хочу написать директиву и использовать ее, чтобы показать/скрыть это small.error
, если min
и max
имеют значения, но min > max
. Как я могу получить доступ к обоим полям внутри одной директивы? Является ли директива подходящим инструментом для этой работы?
Ответы
Ответ 1
Много способов скинуть кошку.
PLUNKER
app.directive('lowerThan', [
function() {
var link = function($scope, $element, $attrs, ctrl) {
var validate = function(viewValue) {
var comparisonModel = $attrs.lowerThan;
if(!viewValue || !comparisonModel){
// It valid because we have nothing to compare against
ctrl.$setValidity('lowerThan', true);
}
// It valid if model is lower than the model we're comparing against
ctrl.$setValidity('lowerThan', parseInt(viewValue, 10) < parseInt(comparisonModel, 10) );
return viewValue;
};
ctrl.$parsers.unshift(validate);
ctrl.$formatters.push(validate);
$attrs.$observe('lowerThan', function(comparisonModel){
// Whenever the comparison model changes we'll re-validate
return validate(ctrl.$viewValue);
});
};
return {
require: 'ngModel',
link: link
};
}
]);
Использование:
<input name="min" type="number" ng-model="field.min" lower-than="{{field.max}}" />
<span class="error" ng-show="form.min.$error.lowerThan">
Min cannot exceed max.
</span>
Ответ 2
Вам не нужна директива. Просто назначьте минимальное значение max min-value. Как:
<input name="min" type="number" ng-model="field.min"/>
<input name="max" type="number" ng-model="field.max" min=" {{ field.min }}"/>
И вам не нужна настройка.
Подробнее: вы можете сделать min=" {{ field.min + 1}}"
Ответ 3
Было бы вам простое сравнение?
<small class="error" ng-show="field.min > field.max">
Я думаю, что директива будет излишним, если ваше дело именно так. Если вы не чувствуете себя комфортно с представлением, содержащим логику приложения, вы можете экспортировать его в функцию контроллера:
$scope.isMinMaxInalid = function() {
return $scope.field.min > $scope.field.max;
};
И шаблон:
<small class="error" ng-show="isMinMaxInalid()">
Ответ 4
Для меня, помимо сообщения с обратной связью, мне нужно определить поле как недействительное, предотвращая отправку. Поэтому я собрал несколько подходов, например, подход @thestewie, с конфигурацией вида для сбора решения для сравнения дат. Надеюсь, мы сможем объединить представленные решения.
Код находится в PLUNKER
angular.module('MyApp')
.directive('thisEarlierThan', function () {
return {
require: 'ngModel',
restrict: 'A',
link: function (scope, elem, attrs, ctrl) {
var startDate,
endDate;
scope.$watch(attrs.ngModel, function (newVal, oldVal, scope) {
startDate = newVal;
check();
});
scope.$watch(attrs.thisEarlierThan, function (newVal, oldVal, scope) {
endDate = newVal;
check();
});
var check = function () {
if (typeof startDate === 'undefined' || typeof endDate === 'undefined') {
return;
}
if (!validate(startDate)) {
startDate = new Date(startDate);
if (!validate(startDate)) {
return;
}
}
if (!validate(endDate)) {
endDate = new Date(endDate);
if (!validate(endDate)) {
return;
}
}
if (startDate < endDate) {
ctrl.$setValidity('thisEarlierThan', true);
}
else {
ctrl.$setValidity('thisEarlierThan', false);
}
return;
};
var validate = function (date) {
if (Object.prototype.toString.call(date) === '[object Date]') {
if (isNaN(date.getTime())) {
return false;
}
else {
return true;
}
}
else {
return false;
}
};
}
};
})
;
Ответ 5
Моя версия директивы:
module.directive('greaterThan', function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attributes, ngModelController) {
var otherValue;
scope.$watch(attributes.greaterThan, function (value) {
otherValue = value;
ngModelController.$validate();
});
ngModelController.$parsers.unshift(function (viewValue) {
ngModelController.$setValidity('greaterThan', !viewValue || !otherValue || viewValue > otherValue);
return viewValue;
});
}
};
});
Ответ 6
Вы можете взглянуть на https://github.com/nelsonomuto/angular-ui-form-validation
Это обеспечивает директиву, которая предварительно сконфигурирована с помощью api, которая предоставляет область видимости и ее модели для вашей функции валидатора.
Вот плункер с вашим конкретным прецедентом: http://plnkr.co/edit/S0rBlS?p=preview
Синтаксис для валидаторов директив приведен в следующем примере:
{
errorMessage: 'Cannot contain the number one',
validator: function (errorMessageElement, val, attr, element, model, modelCtrl){
/**
* The model and modelCtrl(scope) are exposed in the validator function
* */
return /1/.test(val) !== true;
}
}