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

Как сделать reset форму, включая удаление всех ошибок проверки?

У меня есть форма Angular. Поля проверяются с помощью атрибута ng-pattern. У меня также есть кнопка reset. Я использую Ui.Utils Event Binder для обработки события reset следующим образом:

<form name="searchForm" id="searchForm" ui-event="{reset: 'reset(searchForm)'}" ng-submit="search()">
  <div>
    <label>
      Area Code
      <input type="tel" name="areaCode" ng-model="areaCode" ng-pattern="/^([0-9]{3})?$/">
    </label>

    <div ng-messages="searchForm.areaCode.$error">
      <div class="error" ng-message="pattern">The area code must be three digits</div>
    </div>
  </div>

  <div>
    <label>
      Phone Number
      <input type="tel" name="phoneNumber" ng-model="phoneNumber" ng-pattern="/^([0-9]{7})?$/">
    </label>

    <div ng-messages="searchForm.phoneNumber.$error">
      <div class="error" ng-message="pattern">The phone number must be seven digits</div>
    </div>
  </div>

  <br>
  <div>
    <button type="reset">Reset</button>
    <button type="submit" ng-disabled="searchForm.$invalid">Search</button>
  </div>
</form>

Как вы можете видеть, когда форма reset вызывает метод reset на $scope. Вот как выглядит весь контроллер:

angular.module('app').controller('mainController', function($scope) {
    $scope.resetCount = 0;

    $scope.reset = function(form) {
        form.$setPristine();
        form.$setUntouched();
        $scope.resetCount++;
    };

    $scope.search = function() {
        alert('Searching');
    };
});

Я звоню form.$setPristine() и form.$setUntouched, следуя советам еще одного вопроса в разделе "Переполнение стека". Единственная причина, по которой я добавил счетчик, заключалась в том, чтобы доказать, что код вызывается (что это такое).

Проблема заключается в том, что даже после перепродажи формы сообщения проверки не исчезают. Вы можете увидеть полный код на Plunker. Вот скриншот, показывающий, что ошибки не исчезают:

Validation Errors

4b9b3361

Ответ 1

Я начал с комментария от @Brett и построил на нем. На самом деле у меня есть несколько форм, и каждая форма имеет много полей (больше, чем показано только двумя). Поэтому я хотел получить общее решение.

Я заметил, что объект Angular form имеет свойство для каждого элемента управления (input, select, textarea и т.д.), а также некоторые другие свойства Angular. Однако каждый из свойств Angular начинается со знака доллара ($). Поэтому я закончил это (включая комментарий для других программистов):

$scope.reset = function(form) {
    // Each control (input, select, textarea, etc) gets added as a property of the form.
    // The form has other built-in properties as well. However it easy to filter those out,
    // because the Angular team has chosen to prefix each one with a dollar sign.
    // So, we just avoid those properties that begin with a dollar sign.
    let controlNames = Object.keys(form).filter(key => key.indexOf('$') !== 0);

    // Set each control back to undefined. This is the only way to clear validation messages.
    // Calling `form.$setPristine()` won't do it (even though you wish it would).
    for (let name of controlNames) {
        let control = form[name];
        control.$setViewValue(undefined);
    }

    form.$setPristine();
    form.$setUntouched();
};

Ответ 2

Кажется, нет простого способа reset ошибки $в angular. Лучшим способом, вероятно, будет перезагрузка текущей страницы, чтобы начать с новой формы. В качестве альтернативы вам нужно удалить всю ошибку $вручную с помощью этого script:

form.$setPristine(true);
form.$setUntouched(true);

// iterate over all from properties
angular.forEach(form, function(ctrl, name) {
  // ignore angular fields and functions
  if (name.indexOf('$') != 0) {
    // iterate over all $errors for each field        
    angular.forEach(ctrl.$error, function(value, name) {
      // reset validity
      ctrl.$setValidity(name, null);
    });
  }
});
$scope.resetCount++; 

Ответ 3

Вы можете добавить флаг проверки и показать или скрыть ошибки в соответствии со своим значением с помощью ng-if или ng-show в вашем HTML. Форма имеет флаг $valid, который вы можете отправить своему контроллеру.

ng-if удалит или воссоздает элемент в DOM, а ng-show добавит его, но не покажет его (в зависимости от значения флага).

EDIT. Как указал Майкл, если форма отключена, то, как я указал, не будет работать, потому что форма никогда не отправляется. Обновлен код.

HTML

<form name="searchForm" id="searchForm" ui-event="{reset: 'reset(searchForm)'}" ng-submit="search()">
  <div>
    <label>
      Area Code
      <input type="tel" name="areaCode" ng-model="areaCode" ng-pattern="/^([0-9]{3})?$/">
    </label>

    <div ng-messages="searchForm.areaCode.$error">
      <div class="error" ng-message="pattern" ng-if="searchForm.areaCode.$dirty">The area code must be three digits</div>
    </div>
  </div>

  <div>
    <label>
      Phone Number
      <input type="tel" name="phoneNumber" ng-model="phoneNumber" ng-pattern="/^([0-9]{7})?$/">
    </label>

    <div ng-messages="searchForm.phoneNumber.$error">
      <div class="error" ng-message="pattern" ng-if="searchForm.phoneNumber.$dirty">The phone number must be seven digits</div>
    </div>
  </div>

  <br>
  <div>
    <button type="reset">Reset</button>
    <button type="submit" ng-disabled="searchForm.$invalid">Search</button>
  </div>
</form>

JS

$scope.search = function() {
    alert('Searching');
};

$scope.reset = function(form) {
     form.$setPristine();
     form.$setUntouched();
     $scope.resetCount++;
 };

Codepen с рабочим решением: http://codepen.io/anon/pen/zGPZoB

Ответ 4

      $scope.search = {areaCode: xxxx, phoneNumber: yyyy}

Структура всех моделей в вашей форме в одном месте, как указано выше, чтобы вы могли ее очистить следующим образом:

      $scope.search = angular.copy({});

После этого вы можете просто называть это для reset валидацией:

      $scope.search_form.$setPristine();
      $scope.search_form.$setUntouched();
      $scope.search_form.$rollbackViewValue();

Ответ 5

Похоже, я должен сделать правильное поведение в reset. К сожалению, использование стандартного reset не удалось. Я также не включаю библиотеку ui-event. Поэтому мой код немного отличается от вашего, но он делает то, что вам нужно.

<form name="searchForm" id="searchForm" ng-submit="search()">
  pristine = {{searchForm.$pristine}} valid ={{searchForm.$valid}}
  <div>
    <label>
      Area Code
      <input type="tel" required name="areaCode" ng-model="obj.areaCode" ng-pattern="/^([0-9]{3})?$/" ng-model-options="{ allowInvalid: true }">
    </label>

    <div ng-messages="searchForm.areaCode.$error">
      <div class="error" ng-message="pattern">The area code must be three digits</div>
      <div class="error" ng-message="required">The area code is required</div>
    </div>
  </div>

  <div>
    <label>
      Phone Number
      <input type="tel" required name="phoneNumber" ng-model="obj.phoneNumber" ng-pattern="/^([0-9]{7})?$/" ng-model-options="{ allowInvalid: true }">
    </label>

    <div ng-messages="searchForm.phoneNumber.$error">
      <div class="error" ng-message="pattern">The phone number must be seven digits</div>
      <div class="error" ng-message="required">The phone number is required</div>
    </div>
  </div>

  <br>
  <div>
    <button ng-click="reset(searchForm)" type="reset">Reset</button>
    <button type="submit" ng-disabled="searchForm.$invalid">Search</button>
  </div>
</form>

И JS:

$scope.resetCount = 0;
$scope.obj = {};
$scope.reset = function(form_) {
  $scope.resetCount++;
  $scope.obj = {};
  form_.$setPristine();
  form_.$setUntouched();
  console.log($scope.resetCount);
};

$scope.search = function() {
  alert('Searching');
};

Пример в реальном времени на jsfiddle.

Обратите внимание на директиву ng-model-options="{allowinvalid: true}". Используйте это обязательно или до тех пор, пока поле ввода не будет действительным, значение модель не будет записано. Поэтому reset не будет работать.

P.S. Значение put (areaCode, phoneNumber) на объекте упрощает очистку.

Ответ 6

После меня работали

let form = this.$scope.myForm;   
let controlNames = Object.keys(form).filter(key => key.indexOf('$') !== 0);
for (let name of controlNames) {
    let control = form [name];
    control.$error = {};
}

Вкратце:, чтобы избавиться от ошибок ng-сообщений, вам нужно очистить объект $error для каждого элемента формы.

Ответ 7

дальше к ответу @battmanz, но без использования синтаксиса ES6 для поддержки старых браузеров.

 $scope.resetForm = function (form) {

            try {
                var controlNames = Object.keys(form).filter(function (key) { return key.indexOf('$') !== 0 });

                console.log(controlNames);
                for (var x = 0; x < controlNames.length; x++) {
                    form[controlNames[x]].$setViewValue(undefined);
                }

                form.$setPristine();
                form.$setUntouched();
            } catch (e) {                
                console.log('Error in Reset');
                console.log(e);
            }

        };

Ответ 8

Вы можете передать свой объект loginForm в функцию ng-click="userCtrl.login(loginForm) и в вызове функции

this.login = function (loginForm){
  loginForm.$setPristine();
  loginForm.$setUntouched();
}

Ответ 9

У меня была такая же проблема и я попытался сделать решение battmanz (принятый ответ).

Я уверен, что его ответ действительно хорош, но для меня он не работал.

Я использую ng-model для привязки данных и angular библиотеку материалов для входов и директив ng-message для сообщения об ошибке, поэтому, возможно, я скажу, что это будет полезно только для людей используя ту же конфигурацию.

Я много посмотрел на объект formController в javascript, на самом деле существует много функций $ angular, которые отмечены battmanz, и есть, кроме того, ваши имена полей, которые являются объектами с некоторыми функциями в своем поля.

Итак, что очищает вашу форму?

Обычно я вижу форму как объект json, и все поля привязаны к ключу этого json-объекта.

//lets call here this json vm.form
vm.form = {};

//you should have something as ng-model = "vm.form.name" in your view

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

vm.form = {};

И как объясняется в этом вопросе, ng-сообщения не исчезнут с этим, что очень плохо.

Когда я использовал решение battmanz, когда он его написал, сообщения больше не появлялись, но поля после этого не были пустыми, даже если я написал

vm.form = {};

И я выяснил, что это нормально, потому что, используя его решение, фактически удаляет привязку модели из формы, потому что она устанавливает все поля в undefined. Таким образом, текст все еще был в представлении, потому что каким-то образом он больше не привязывался, и он решил остаться в HTML.

Итак, что я сделал?

Собственно, я просто очищаю поле (устанавливая привязку к {}) и использую просто

form.$setPristine();
form.$setUntouched();

На самом деле это кажется логичным, так как привязка все еще здесь, значения в форме теперь пусты, а директива angular ng-messages запускается только в том случае, если форма не является нетронутой, поэтому я считаю ее нормальной в конце концов.

Последний (очень простой) код:

function reset(form) {
        form.$setPristine();
        form.$setUntouched();
};

Большая проблема, с которой я столкнулся:

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

Когда я снова щелкнул, дата отправки была пуста. Это еще более странно, потому что моя кнопка отправки должна быть отключена, когда требуемое поле не заполнено хорошим шаблоном, а пустое, конечно, не очень хорошее.

Я не знаю, является ли мой способ делать лучший или даже правильный, если у вас есть какой-либо критик/предложение или хоть что-то о проблеме, с которой я столкнулся, пожалуйста, дайте мне знать, я всегда люблю активировать angularJS.

Надеюсь, это поможет кому-то и извините за плохой английский.

Ответ 10

Таким образом, ни один из ответов не работал полностью для меня. Esp, очищая значение представления, поэтому я объединил все ответы, очистив значение вида, очистив ошибки и очистив выбор с помощью j-запроса (при условии ввода полей и имени так же, как имя модели)

 var modelNames = Object.keys($scope.form).filter(key => key.indexOf('$') !== 0);
                    modelNames.forEach(function(name){
                        var model = $scope.form[name];
                        model.$setViewValue(undefined);
                        jq('input[name='+name+']').val('');
                        angular.forEach(model.$error, function(value, name) {
                          // reset validity
                          model.$setValidity(name, null);
                        });
                    });
                    $scope.form.$setPristine();
                    $scope.form.$setUntouched();