Динамічна перевірка 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.