2015-06-23 49 views
17

我有一个角度的形式。这些字段使用ng-pattern属性进行验证。我也有一个重置按钮。我使用的是​​3210处理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> 

正如你所看到的,当表单被重置它呼吁$scopereset方法。这里是整个控制器的样子:

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,以下从another question这里对堆栈溢出的意见。我添加计数器的唯一原因是要证明代码正在被调用(它是什么)。

问题是,即使重新设置窗体后,验证消息也不会消失。您可以在Plunker上看到完整的代码。下面是显示该错误不会消失截图:

Validation Errors

+2

只有似乎事为我工作是手动重置每个表单变量(即'form.areaCode ='';'和'form.phoneNumber ='';')。这就是你通常会这样做的方式。 – Brett

回答

19

我开始从@Brett评论,并在其建造的。我实际上有多种形式,每种形式都有很多领域(不仅仅是所示的两个领域)。所以我想要一个通用解决方案。

我注意到角度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'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(); 
}; 
+4

注意别人,这种方法可以有效地总结如下:“'form. $ setPristine()'不会清除错误,你必须将所有的表单控件明确地设置为'undefined'”。 – rinogo

+0

'未定义'是不可能的!稍后再次让该字段重新验证自己,似乎不可能,只能访问表单数据。不知道如果我错过了...... :(我已经尝试过'form.Field。$ setDirty(true); form.Field。$ validate(); form。$ setSubmitted();'它并不工作。 – user2173353

4

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

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

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

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

+0

使用此解决方案,您将看不到任何错误,因为** Search **按钮被禁用,您无法触发“搜索”功能来显示错误。另一个简单的方法是检查输入字段是否脏:'ng-if =“searchForm.phoneNumber。$ dirty”' – Michael

+1

错过了ng-disabled,我的错误,我会用你的建议Michael更新代码。感谢您指出了这一点。 – Ariel

+0

我不想隐藏验证消息,因为@Michael指出,只要表单无效,我就会禁用提交按钮。我需要表单在复位后实际上是有效的(而不仅仅是有效的)。 – battmanz

5

似乎有没有在角重置$错误的简单方法。最好的方法可能是重新加载当前页面,以新的表单开始。另外,您都必须使用该脚本手动删除所有$错误:

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

你可以通过你的登录表单对象插入功能ng-click="userCtrl.login(loginForm) 并在函数调用

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

没有解决手头上的问题 – Vasily

2

它看起来像我该怎么做在重置正确的行为。不幸的是,使用标准重置失败。我也不包括图书馆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}"。一定使用它,或者直到输入字段无效,型号值不被记录。因此,重置将不会运行。

P.S.将对象上的值(areaCode,phoneNumber)简化为纯化。

+0

答案是完美的,只有我想给它添加一个点,如果你在你的reset中调用了'form _。$ setPristine();'和'form _。$ setUntouched();'函数,那么'ng-invalid'类将消失,因此表单字段将不会被标记为红色 – Musa

+0

这对我有用ng-model-options =“{allowInvalid:true}”这非常有帮助。与此有一段时间。 –

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

结构表单中的所有车型在同一个地方像上面,这样你就可以清除它是这样的:

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

之后,你可以叫这为重新验证:

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

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

     }; 
2

继为我工作

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-信息的错误,你需要清除出$错误对象为每个表单项目。

0

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

我很确定他的回答非常好,但是对我而言这并不奏效。

我正在使用ng-model绑定数据,输入的角度材质库和ng-message指令的错误消息为,所以也许我会说只对使用相同配置的人有用。

我花了很多时间来看待javascript中的formController对象,事实上battmanz提到了很多$ angular函数,还有一些字段名称,它们是字段中的某些函数的对象。

那么什么是清理你的表单?

通常我会将表单看作json对象,并且所有字段都绑定到此json对象的键。

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

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

因此,在第一次清楚,我只是做了submiting形式的回调形式:

vm.form = {}; 

而在这个问题上的解释,NG的消息将不会与消失,这是非常糟糕的。

当我用battmanz的解决方案,因为他写的,这些消息没有再出现,但该领域是不是空submiting后了,即使我写

vm.form = {}; 

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

那么我做了什么?

其实我只是清除该字段(设置绑定到{}),并用刚刚

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

其实这似乎是合乎逻辑的,因为绑定是还在这里,在表单中值现在是空的,并且角度ng-messages指令只在表单没有被触及时触发,所以我认为这是正常的。

决赛(很简单)的代码是:

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

一个大问题,我与遇到:

只有一次,回调似乎在什么地方搞砸了,不知何故字段不是空的(就像我没有点击提交按钮)。

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

我不知道我的做法是最好甚至是正确的,如果您对我遇到的问题有任何批评意见或建议,请告诉我,我总是喜欢以angularJS 。

希望这会帮助别人,并对坏英语感到抱歉。

0

所以没有任何答案完全为我工作。 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(); 
相关问题