2016-08-05 2 views
0

Я пытаюсь добавить пользовательскую функцию проверки в Angg's ngMessages.Угловые ngMessages - Доступ к нескольким значениям формы

В частности, я хочу значение нескольких входов (количество входов будет динамичным, но сейчас придерживаться 2) в общей сложности 100.

Я создал новую директиву под названием totalOneHundred которая запуска на изменение формы, но я не могу понять, как получить доступ к другим значениям формы из обратного вызова link:.

Я разместил свой код ниже. Есть что-то, чего я не хватает? Кроме того, если есть лучший способ выполнить это (например, функция sum() в контроллере и ng-show), пожалуйста, позвоните мне.

Благодарим за помощь.

Форма:

<!-- input box to be validated --> 
<input type="number" class="form-control" name="lowBound" ng-model="ctrl.lowBound" total-one-hundred required> 

<!-- validation messages --> 
<div ng-messages="form['lowBound'].$error" role="alert"> 
    <div ng-message="required">Cannot be empty</div> 
    <div ng-message="totalOneHundred">Sum of tasks must = 100</div> 
</div> 

<!-- input box to be validated --> 
<input type="number" class="form-control" name="highBound" ng-model="ctrl.highBound" total-one-hundred required> 

<!-- validation messages --> 
<div ng-messages="form['highBound'].$error" role="alert"> 
    <div ng-message="required">Cannot be empty</div> 
    <div ng-message="totalOneHundred">Sum of tasks must = 100</div> 
</div> 

директива:

return { 
    restrict: "A", 

    require: ["^^form", "ngModel"], 

    link: function(scope, element, attributes, controllers) { 

     // At first, form is assigned the actual form controller... 
     const form = controllers[0]; 
     const model = controllers[1]; 

     model.$validators.totalOneHundred = function (modelValue, form, element, scope) { 

      // however, the value of form here is "1". 
      // modelValue is the value of the triggering input, 
      // but how can I access the other form inputs? 
      return true; 

     }; 

    } 
}; 

ответ

1

Сначала я взял код и реализован this fiddle. A sum() метод родительского контроллера вычисляет общее количество (простое в скрипке, но поскольку родительский контроллер знает всю динамическую модель, он также возможен в реальном случае). total-one-hundred берет сумму в качестве аргумента, т.е .:

<input type="number" class="form-control" name="lowBound" ng-model="ctrl.lowBound" 
    total-one-hundred="ctrl.sum()" required /> 

Увы, он не работает правильно! Проблема: каждый вход отображает ошибку «Сумма задач должна = 100». Если вы измените поле и общее станет правильным, это поле станет действительным и перестанет отображать сообщение. Но в других областях нет!


EDIT: Ну, может работа даже этот путь. Секрет состоит в том, чтобы добавить часы на сумму для каждой директивы проверки и повторно применить валидацию в этом поле; новая функция ссылки:

link: function(scope, element, attributes, controllers) { 
     const model = controllers[0]; 
     var totalEvaluator = $parse(attributes['totalOneHundred']); 

     scope.$watch(totalEvaluator, function(newval, oldval) { 
     if(newval !== oldval) { 
      model.$validate(); 
     } 
     }) 

     model.$validators.totalOneHundred = function (modelValue) { 
     return totalEvaluator(scope) === 100; 
     }; 
    } 

(! ВНИМАНИЕ, что это стоит дополнительных часов за поле)

Теперь однако sum() функции (которая потенциально может быть дорогой) называется много раз. Наблюдая за входами этой функции и вызывая ее только тогда, когда они меняются, может улучшить ситуацию.

Обновленный скрипку: (. Я до сих пор предпочитают проверки достоверности моделей -см последний paragraph-, но это хорошо, чтобы быть в курсе всех альтернатив и их побочных эффектов) https://jsfiddle.net/m8ae0jea/1/


Это концептуальная проблема кросс-полевые проверки. Где относится валидация? Если вы можете реорганизовать свою модель, поэтому все, что проверяется, является целым объектом, тогда вы можете использовать пользовательские элементы управления Angular, как в this fiddle.

Теперь модель выглядит следующим образом:

this.model = { 
    lowBound: <a number>, 
    highBound: <a number> 
}; 

И есть редактор для всей модели, в комплекте со своими собственными сообщениями:

<model-editor name="entireModel" ng-model="ctrl.model" form="form" 
    total-one-hundred="ctrl.sum()"></model-editor> 
<div ng-messages="form['entireModel'].$error" role="alert"> 
    <div ng-message="totalOneHundred">Sum of tasks must = 100</div> 
</div> 

Как вы можете видеть, общая проверка относится к целая модель.

Второй пример работает правильно, если вы можете прожить всего лишь одно сообщение для всей «общей» проверки. Но мне это не нравится ...

Угловая проверка (IMHO) - быстрое и грязное решение, подходящее для простых вещей. Скажем, что поле не должно быть пустым, другое поле должно соответствовать регулярному выражению и т. Д. Для сложных вещей (например, этот случай) я считаю нецелесообразным определять бизнес-логику в представлении. Я предпочитаю делать проверку модели и привязывать результаты проверки с помощью Angular. В этой степени я создал egkyron, который хорошо подходит для таких вещей.

+0

Большое спасибо за подробный ответ. Вероятно, я пытаюсь подтолкнуть угловую проверку слишком далеко. Я посмотрю на ресурсы, которые вы связали, и посмотрите, что подходит для моего использования. Еще раз спасибо! – Mac

Смежные вопросы