Подтвердить что ты не робот

Angular.js - ng-change не срабатывает, когда ng-pattern недействителен

Я использую ng-pattern для проверки некоторых полей формы, и я использую ng-change с ним для просмотра и обработки любых изменений, однако ng-change (или $scope. $watch) будет срабатывать только тогда, когда элемент формы находится в правильном состоянии! Я новичок в angular, поэтому я не знаю, как решить эту проблему, хотя я подозреваю, что новая директива - это путь.

Как я могу заставить ng-change запускаться как в $invalid, так и в состоянии $valid form, поскольку ng-pattern все еще устанавливает состояния элемента формы, как и раньше?

Html:

<div ng-app="test">
  <div ng-controller="controller">
    <form name="form">
        <input type="text" name="textbox" ng-pattern="/^[0-9]+$/" ng-change="change()" ng-model="inputtext"> Changes: {{ changes }}
    </form>

    <br>
    Type in any amount of numbers, and changes should increment.

    <br><br>
    Now enter anything that isn't a number, and changes will stop incrementing. When the form is in the $invalid state, ng-change doesn't fire.

    <br><br>
    Now remove all characters that aren't numbers. It will increment like normal again. When the form is in the $valid state, ng-change will fire.

    <br><br>
    I would like ng-change to fire even when the the form is $invalid.

    <br><br>
        form.$valid: <font color="red">{{ form.$valid }}</font>

  </div>
</div>

JavaScript:

angular.module('test', []).controller('controller', function ($scope) {
    $scope.changes = 0;
    $scope.change = function () {
        $scope.changes += 1;
    };
});

Я создал рабочий скрипт JS, который показывает проблему, с которой я сталкиваюсь.

http://jsfiddle.net/JAN3x/1/

Кстати, эта проблема angular также кажется актуальной: https://github.com/angular/angular.js/issues/1296

4b9b3361

Ответ 1

Изменить. На это был дан ответ, когда ng-model-options недоступен. Пожалуйста, см. Ответ на верхний голос.

вы можете написать простую директиву для прослушивания события input.

HTML:

<input type="text" name="textbox" ng-pattern="/^[0-9]+$/" watch-change="change()" ng-model="inputtext"> Changes: {{ changes }}

JS:

app.directive('watchChange', function() {
    return {
        scope: {
            onchange: '&watchChange'
        },
        link: function(scope, element, attrs) {
            element.on('input', function() {
                scope.$apply(function () {
                    scope.onchange();
                });
            });
        }
    };
});

http://jsfiddle.net/H2EAB/

Ответ 2

Вы можете изменить поведение своих входов с помощью опций ng-model.

Просто добавьте этот атрибут к своему входу, и событие ng-change будет срабатывать:

      ng-model-options="{allowInvalid: true}"

см. https://docs.angularjs.org/api/ng/directive/ngModelOptions

Ответ 3

вам просто нужно добавить

 ng-model-options="{ updateOn: 'default' , allowInvalid:'true'}"

это указывает на то, что модель может быть установлена ​​со значениями, которые не корректно проверялись, а не по умолчанию.

Ответ 4

Вдохновленный гениальным решением Li Yin Kong:

В его решении есть проблема с обновлением ndModel (см. комментарии к его сообщению).

Мое исправление существенно изменяет тип области действия директивы. Он позволяет директивному доступу к области (и методам) контроллера, Затем директиве watch-change больше не нужна "инструкция для eval" (change()), а только "имя метода контроллера для вызова" (change).

И чтобы получить новое значение ввода в этой функции, я передаю контекст (это = сам ввод). Поэтому я могу получить значение или любое его свойство.

Таким образом, нам не нужны обновления ngModel (или если форма недействительна, что является еще одной проблемой исходного решения: ngModel удаляется, если форма недействительна)

HTML:

<input type="text" name="textbox" ng-pattern="/^[0-9]+$/" watch-change="change" ng-model="inputtext">

JAVASCRIPT:

app.directive('watchChange', function() {
    return {
        restrict : 'A',
        link: function(scope, element, attrs) {
            element.on('input', function(){
                scope[attrs.watchChange](this);
            })
        }
    };
});

DEMO: http://jsfiddle.net/msieurtoph/0Ld5p2t4/