Динамічна перевірка ng-шаблону Angularjs


84

У мене є форма, яка, якщо прапорець встановлений як false, примушує перевірку на введенні тексту за допомогою директиви ng-required. Якщо прапорець істинний, поле приховується, а ng-required встановлюється як false.

Проблема полягає в тому, що у мене також є регулярний вираз для перевірки, вказаний на вході, а також використовуючи директиву ng-pattern angular. Проблема, з якою я стикаюся, полягає в тому, що якщо користувач вводить невірний номер телефону, ставить прапорець, щоб деактивувати цей вхід (і, отже, не потребує подальшої перевірки), форма не дозволить подання, оскільки вона є недійсною на основі ng-шаблону.

Я спробував вирішити цю проблему, додавши функцію ng-change, щоб встановити для вхідної моделі значення null, проте ng-шаблон і, таким чином, поле все ще встановлено як недійсне в початковому наборі прапорця на false. Однак, якщо я знімаю прапорець, повертаючи все до початкового завантаження форми, то знову встановлюю цей прапорець, форма є дійсною і може подавати. Я не впевнений, чого мені не вистачає. Ось код ng-зміни, який я маю до цього часу:

    var phoneNumberRegex = /^\(?(\d{3})\)?[ .-]?(\d{3})[ .-]?(\d{4})$/;
    $scope.phoneNumberPattern = phoneNumberRegex;
    $scope.removeValidation = function() {
        if ($scope.cell._newUser === false) {
            $scope.request._number = '';
            $scope.phoneNumberPattern = /[0-9a-zA-Z]?/;
        } else {
            $scope.phoneNumberPattern = phoneNumberRegex;
        }
    };

Відповіді:


175

Це цікава проблема, складна кутова перевірка. Наступна скрипка реалізує те, що ви хочете:

http://jsfiddle.net/2G8gA/1/

Деталі

Я створив нову директиву, rpatternтобто поєднання Angular's ng-requiredта ng-patternкоду з input[type=text]. Для цього слід спостерігати за requiredатрибутом поля та враховувати це під час перевірки за допомогою регулярного виразу, тобто, якщо не потрібно, позначте поле як valid-pattern.

Примітки

  • Велика частина коду - від Angular, з урахуванням потреб цього.
  • Коли прапорець встановлений, поле обов’язкове.
  • Поле не приховується, якщо потрібний прапорець хибний.
  • Регулярний вираз спрощений для демонстрації (дійсний - 3 цифри).

Забруднений (але менше) рішення, якщо ви не хочете , нову директиву, буде що - щось на кшталт:

$scope.phoneNumberPattern = (function() {
    var regexp = /^\(?(\d{3})\)?[ .-]?(\d{3})[ .-]?(\d{4})$/;
    return {
        test: function(value) {
            if( $scope.requireTel === false ) {
                return true;
            }
            return regexp.test(value);
        }
    };
})();

А в HTML зміни не потрібні:

<input type="text" ng-model="..." ng-required="requireTel"
    ng-pattern="phoneNumberPattern" />

Це насправді обманює кутовий виклик нашого test() методу, а не того RegExp.test(), що враховує required.


2
Мені було б дуже цікаво дізнатися, що роблять круглі дужки, що оточують та після функції. Без них не працює
NeedHack

5
Вони викликають функцію безпосередньо, ефективно розміщуючи її значення, що повертається, до змінної. Це дуже поширене у Javascript, щоб не забруднювати зовнішній обсяг деталями реалізації конкретного компонента, наприклад, поглянути на шаблон модуля .
Нікос Параскевопулос

6
Брудне рішення, щоб зіграти фокус на AngularJS, заснований на "качинній машині" JS, є найдивовижнішим кодом, який я бачив сьогодні. Дійсно розумне рішення!
Флоріан Лох

Дякуємо за чудовий код, але все ще не дуже зрозумілий, 1) згідно docs.angularjs.org/api/ng/directive/input , "Якщо вираз оцінюється як об'єкт RegExp, то це використовується безпосередньо. Якщо вираз оцінює у рядок, тоді він буде перетворений у RegExp ", але я думаю, phoneNumberPattern є об'єктом при поверненні? Це повинен бути Regxp Obj? 2) А в тесті функції (значення) {}, звідки береться параметр "значення"? Оцініть будь-які відповіді!
user2499325

1
1) Застереження "Якщо вираз оцінюється як RegExp" реалізовано Angular, перевіряючи, чи має річ, яку він отримує, testметод. Ось чому ми надаємо йому об’єкт з нашим власним користувацьким test()кодом, по суті наслідуючи рідну JS RegExp. 2) valueЗвичайно, передається Angular при виконанні фактичної перевірки дійсності.
Нікос Параскевопулос

25

Не віднімаючи нічого від чудової відповіді Нікоса, можливо, ви можете зробити це простіше:

<form name="telForm">
  <input name="cb" type='checkbox' data-ng-modal='requireTel'>
  <input name="tel" type="text" ng-model="..." ng-if='requireTel' ng-pattern="phoneNumberPattern" required/>
  <button type="submit" ng-disabled="telForm.$invalid || telForm.$pristine">Submit</button>
</form>

Зверніть увагу на другий вхід: ми можемо використовувати a ng-ifдля контролю візуалізації та перевірки у формах. Якщо requireTelзмінна не встановлена, другий вхід буде не тільки прихований, але й взагалі не відображатиметься, таким чином форма пройде перевірку, і кнопка стане ввімкненою, і ви отримаєте те, що вам потрібно.


1
Зверху - це просто. Недоліком є ​​те, що будь-які вхідні дані, які видаляються, коли вираз ng-if хибний, у них видалятимуть будь-який текст, якщо потім ng-if обчислюється як істина. Все-таки +1 для простоти.
Бред

Я хотів додати, якщо ви пройдете цей шлях, переконайтеся, що розумієте, що все в ng-if (якщо ви поставите його на div) тепер матиме власний обсяг.
Бред

5

Використовуваний візерунок:

 ng-pattern="/^\d{0,9}(\.\d{1,9})?$/"

Використаний довідковий файл:

 '<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js"></script>'

Приклад для введення:

 <input type="number" require ng-pattern="/^\d{0,9}(\.\d{1,9})?$/"><input type="submit">


2

Я щойно наткнувся на це днями.

Те, що я зробив, що здається простішим, ніж вище, це встановити шаблон на змінну в області дії та звернутися до неї у ng-шаблоні у поданні.

Коли "прапорець не встановлений", я просто встановлюю значення регулярного виразу на /.*/ у зворотному виклику onChanged (якщо перейти до позначки). ng-pattern вибирає, що змінюється, і каже: "Добре, ваше значення добре". Форма дійсна. Я б також видалив з поля непогані дані, щоб у вас не було явного поганого # телефону.

У мене були додаткові проблеми з ng-required, і я зробив те саме. Працював як оберіг.


0

Встановлює ключ помилки перевірки шаблону, якщо ngModel $ viewValue не відповідає RegExp, знайденому шляхом обчислення виразу Angular, вказаного у значенні атрибута. Якщо вираз обчислює об'єкт RegExp, це використовується безпосередньо. Якщо вираз обчислюється як рядок, він буде перетворений у RegExp після обертання його символами ^ та $.

Здається, що найбільш голосована відповідь у цьому питанні повинна бути оновлена, тому що коли я її спробую, вона не застосовує testфункції та перевірка не працює.

Приклад з Angular docs мені добре підходить:

Модифікація вбудованих валідаторів

html

<form name="form" class="css-form" novalidate>
  <div>
   Overwritten Email:
   <input type="email" ng-model="myEmail" overwrite-email name="overwrittenEmail" />
   <span ng-show="form.overwrittenEmail.$error.email">This email format is invalid!</span><br>
   Model: {{myEmail}}
  </div>
</form>

js

var app = angular.module('form-example-modify-validators', []);

app.directive('overwriteEmail', function() {
    var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+@example\.com$/i;

    return {
        require: 'ngModel',
        restrict: '',
        link: function(scope, elm, attrs, ctrl) {
            // only apply the validator if ngModel is present and Angular has added the email validator
            if (ctrl && ctrl.$validators.email) {

                // this will overwrite the default Angular email validator
                ctrl.$validators.email = function(modelValue) {
                    return ctrl.$isEmpty(modelValue) || EMAIL_REGEXP.test(modelValue);
                };
             }
         }
     };
 });

Планкер


-1

Ви можете використовувати сайт https://regex101.com/ для створення власного шаблону для певної країни:

Наприклад, Польща:

-pattern = xxxxxxxxx OR xxx-xxx-xxx OR xxx xxx xxx 
-regexp ="^\d{9}|^\d{3}-\d{3}-\d{3}|^\d{3}\s\d{3}\s\d{3}"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.