Html 如何重置表单,包括删除所有验证错误?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31010096/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 11:41:45  来源:igfitidea点击:

How do I reset a form including removing all validation errors?

htmlangularjsng-messages

提问by battmanz

I have an Angular form. The fields are validated using the ng-patternattribute. I also have a reset button. I'm using the Ui.Utils Event Binderto handle the resetevent like so:

我有一个 Angular 形式。这些字段使用ng-pattern属性进行验证。我也有一个重置按钮。我正在使用Ui.Utils 事件绑定器来处理这样的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>

As you can see, when the form is reset it calls the resetmethod on the $scope. Here's what the entire controller looks like:

正如你所看到的,当表单被重置它调用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');
    };
});

I'm calling form.$setPristine()and form.$setUntouched, following the advice from another questionhere on Stack Overflow. The only reason I added the counter was to prove that the code is being called (which it is).

我正在调用form.$setPristine()form.$setUntouched,遵循Stack Overflow 上另一个问题的建议。我添加计数器的唯一原因是为了证明代码正在被调用(确实如此)。

The problem is that even after reseting the form, the validation messages don't go away. You can see the full code on Plunker. Here's a screenshot showing that the errors don't go away:

问题是即使在重置表单后,验证消息也不会消失。您可以在Plunker上查看完整代码。这是显示错误不会消失的屏幕截图:

Validation Errors

验证错误

采纳答案by battmanz

I started with the comment from @Brett and built upon it. I actually have multiple forms and each form has many fields (more than just the two shown). So I wanted a general solution.

我从@Brett 的评论开始,并以此为基础。我实际上有多个表单,每个表单都有许多字段(不仅仅是显示的两个)。所以我想要一个通用的解决方案。

I noticed that the Angular formobject has a property for each control (input, select, textarea, etc) as well as some other Angular properties. Each of the Angular properties, though, begins with a dollar sign ($). So I ended up doing this (including the comment for the benefit of other programmers):

我注意到 Angularform对象为每个控件(输入、选择、文本区域等)以及其他一些 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's 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();
};

回答by Antoni Xu

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

Structure all models in your form in one place like above, so you can clear it like this:

像上面一样将表单中的所有模型组织在一个地方,这样你就可以像这样清除它:

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

After that you can just call this for reset the validation:

之后,您可以调用它来重置验证:

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

回答by Michael

There doesn't seem to be an easy way to reset the $errors in angular. The best way would probably be to reload the current page to start with a new form. Alternatively you have to remove all $error manually with this script:

似乎没有一种简单的方法可以在 angular 中重置 $errors。最好的方法可能是重新加载当前页面以从新表单开始。或者,您必须使用此脚本手动删除所有 $error :

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++; 

回答by Ariel

You can add a validation flag and show or hide errors according to its value with ng-ifor ng-showin your HTML. The form has a $valid flag you can send to your controller.

您可以在 HTML 中ng-ifng-show在 HTML 中添加验证标志并根据其值显示或隐藏错误。该表单有一个 $valid 标志,您可以将其发送给您的控制器。

ng-ifwill remove or recreate the element to the DOM, while ng-showwill add it but won't show it (depending on the flag value).

ng-if将删除或重新创建元素到 DOM,同时ng-show将添加它但不会显示它(取决于标志值)。

EDIT: As pointed by Michael, if form is disabled, the way I pointed won't work because the form is never submitted. Updated the code accordingly.

编辑:正如迈克尔所指出的,如果表单被禁用,我指出的方式将不起作用,因为表单从未提交。相应地更新了代码。

HTML

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

JS

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

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

Codepen with working solution: http://codepen.io/anon/pen/zGPZoB

带有工作解决方案的 Codepen:http://codepen.io/anon/pen/zGPZoB

回答by Sumeet

Following worked for me

以下为我工作

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 = {};
}

In Short:to get rid of ng-messages errors you need to clear out the $errorobject for each form item.

简而言之:要摆脱 ng-messages 错误,您需要清除每个表单项的$error对象。

回答by Stepan Kasyanenko

It looks like I got to do the right behavior at reset. Unfortunately, using the standard resetfailed. I also do not include the library ui-event. So my code is a little different from yours, but it does what you need.

看起来我必须在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>

And JS:

和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');
};

Live example on jsfiddle.

jsfiddle上的实时示例。

Note the directive ng-model-options="{allowinvalid: true}". Use it necessarily, or until the entry field will not be valid, the modelvalue is not recorded. Therefore, the reset will not operate.

注意指令ng-model-options="{allowinvalid: true}"。必须使用它,否则在输入字段无效之前,不会记录模型值。因此,复位将不起作用。

P.S. Put value (areaCode, phoneNumber) on the object simplifies purification.

PS Put value (areaCode, phoneNumber) 在对象上简化了净化。

回答by Alburkerk

I had the same problem and tried to do battmanz solution (accepted answer).

我遇到了同样的问题并试图做 battmanz 解决方案(接受的答案)。

I'm pretty sure his answer is really good, but however for me it wasn't working.

我很确定他的回答非常好,但对我来说它不起作用。

I am using ng-model to bind data, and angular material library for the inputs and ng-message directives for error message, so maybe what I will say will be useful only for people using the same configuration.

我正在使用 ng-model 来绑定数据,并使用 angular material library 用于输入和 ng-message 指令用于错误消息,所以也许我要说的只会对使用相同配置的人有用。

I took a lot of look at the formController object in javascript, in fact there is a lot of $ angular function as battmanz noted, and there is in addition, your fields names, which are object with some functions in its fields.

我在javascript中查看了很多formController对象,实际上正如battmanz指出的那样,有很多$ angular函数,此外还有你的字段名称,它们是在其字段中具有一些函数的对象。

So what is clearing your form ?

那么什么是清除你的表格呢?

Usually I see a form as a json object, and all the fields are binded to a key of this json object.

通常我把一个表单看作一个 json 对象,所有的字段都绑定到这个 json 对象的一个​​键上。

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

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

So at first to clear the form I just did callback of submiting form :

所以首先清除表单我只是做了提交表单的回调:

vm.form = {};

And as explained in this question, ng-messages won't disappear with that, that's really bad.

正如在这个问题中所解释的,ng-messages 不会随之消失,这真的很糟糕。

When I used battmanz solution as he wrote it, the messages didn't appear anymore, but the fields were not empty anymore after submiting, even if I wrote

当我在他写的时候使用battmanz解决方案时,消息不再出现,但是提交后字段不再为空,即使我写了

vm.form = {};

And I found out it was normal, because using his solution actually remove the model binding from the form, because it sets all the fields to undefined. So the text was still in the view because somehow there wan't any binding anymore and it decided to stay in the HTML.

我发现这很正常,因为使用他的解决方案实际上从表单中删除了模型绑定,因为它将所有字段设置为未定义。所以文本仍然在视图中,因为不知何故不再有任何绑定,它决定留在 HTML 中。

So what did I do ?

那我做了什么?

Actually I just clear the field (setting the binding to {}), and used just

实际上我只是清除了字段(将绑定设置为 {}),并且只使用了

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

Actually it seems logical, since the binding is still here, the values in the form are now empty, and angular ng-messages directive is triggering only if the form is not untouched, so I think it's normal after all.

其实这似乎是合乎逻辑的,因为绑定仍然在这里,表单中的值现在是空的,并且只有在表单未被触及时才会触发angular ng-messages指令,所以我认为这毕竟是正常的。

Final (very simple) code is that :

最终(非常简单)的代码是:

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

A big problem I encountered with that :

我遇到的一个大问题:

Only once, the callback seems to have fwored up somewhere, and somehow the fields weren't empty (it was like I didn't click on the submit button).

只有一次,回调似乎在某处搞砸了,不知何故这些字段不是空的(就像我没有点击提交按钮一样)。

When I clicked again, the date sent was empty. That even more weird because my submit button is supposed to be disabled when a required field is not filled with the good pattern, and empty is certainly not a good one.

当我再次点击时,发送的日期是空的。这更奇怪,因为当必填字段没有填充好的模式时,我的提交按钮应该被禁用,而空肯定不是一个好模式。

I don't know if my way of doing is the best or even correct, if you have any critic/suggestion or any though about the problem I encountered, please let me know, I always love to step up in angularJS.

我不知道我的做法是最好的还是正确的,如果您对我遇到的问题有任何批评/建议或任何想法,请告诉我,我总是喜欢加强 angularJS。

Hope this will help someone and sorry for the bad english.

希望这会帮助某人并为糟糕的英语感到抱歉。

回答by Abdul Rehman Sayed

further to @battmanz 's answer, but without using any ES6 syntax to support older browsers.

进一步@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);
            }

        };

回答by Diwas Subedi

So none of the answers were completely working for me. Esp, clearing the view value, so I combined all the answers clearing view value, clearing errors and clearing the selection with j query(provided the fields are input and name same as model name)

所以没有一个答案完全适合我。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();

回答by code4j

You can pass your loginForm object into the function ng-click="userCtrl.login(loginForm)and in the function call

您可以将 loginForm 对象传递给函数ng-click="userCtrl.login(loginForm)和函数调用

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