在提交表单时以编程方式将所有表单字段设置为 ng-touched

Posted

技术标签:

【中文标题】在提交表单时以编程方式将所有表单字段设置为 ng-touched【英文标题】:Programmatically set all form fields to ng-touched on form submission 【发布时间】:2015-08-18 03:58:44 【问题描述】:

html

<div class="form-group" 
     ng-class=" 'has-error' : form.firstName.$invalid && form.firstName.$touched ">
  <label for="firstName" 
         class="control-label">
         First Name
  </label>
  <input type="text" 
         name="firstName" 
         id="firstName" 
         ng-model="editableUser.firstName" 
         class="form-control" 
         required>
  <span class="help-block" 
        ng-show="form.firstName.$error.required && form.firstName.$touched">
        First Name is required
  </span>
</div>

<input type="submit" 
       ng-click="submit()" 
       value="Submit" 
       class="btn btn-default">

当用户单击提交时,我试图让我的“有错误”类启动无效字段。

我认为你可以这样做:

$scope.submit = function () 
  if ($scope.form.$invalid) 
    angular.forEach($scope.form.$invalid, function(field) 
      field.$setTouched();
    );
    alert("Form is invalid.");
  
;

但是https://docs.angularjs.org/api/ng/type/form.FormController中没有$setTouched方法

编辑:意识到$setTouched确实存在,它在https://docs.angularjs.org/api/ng/type/ngModel.NgModelController中

【问题讨论】:

您的某个表单域是什么样的?您可以编辑您的问题以包含一个示例吗?我很感兴趣你为什么还要检查 $touched? 如果你改用 setDirty 会怎样? @BenHeymink 添加代码以澄清。 【参考方案1】:
if ($scope.form.$invalid) 
    angular.forEach($scope.form.$error, function (field) 
        angular.forEach(field, function(errorField)
            errorField.$setTouched();
        )
    );
    alert("Form is invalid.");

plunker: http://plnkr.co/edit/XmvoTkIQ0yvFukrVSz11

【讨论】:

像魅力一样工作......拯救了我的一天:P【参考方案2】:

试试最近添加的$submitted

<input type="text" 
     name="firstName" 
     id="firstName" 
     ng-model="editableUser.firstName" 
     class="form-control" 
     required>
   <span class="help-block" 
    ng-show="form.firstName.$error.required && (form.firstName.$touched || form.$submitted">
    First Name is required

【讨论】:

此外 - 如果您的函数是由锚元素而不是提交类型的输入触发的 - 您可能希望将 $scope.myForm.$setSubmitted(); 添加到您的函数中。 我最喜欢这个解决方案 - 如果您可以使用内置逻辑,则无需额外的控制器逻辑! 感谢您提供有关 $submitted 属性的精彩提示!在我的情况下,以下工作正常 - “fullname.invalid && (fullname.touched || form.submitted)”【参考方案3】:

扩展 Alexey 的回答,您可以向 FormController 添加新方法,该方法将执行相同的操作,因此无需将代码从一个提交函数复制到另一个:

// config.js
export default function config($provide) 
    $provide.decorator('formDirective', $delegate => 
        const fn = $delegate[0].controller.prototype
        if (!('$setTouched' in fn)) fn.$setTouched = function() 
            if (this.$invalid) 
                Object.values(this.$error).forEach(controls => 
                    controls.forEach(control => control.$setTouched())
                )
            
        
        return $delegate
    )

// controller.js
$scope.submit = function () 
    if ($scope.form.$invalid) 
        $scope.form.$setTouched();
        alert("Form is invalid.");
    
;

如果有人想知道为什么有人要进行这种验证:缺少 ios 约束验证,因此即使在无效表单上也会调用 ng-submit

【讨论】:

【参考方案4】:

以上答案对我不起作用..以编程方式将 Touched 设置为 true。

示例,即使在执行此$scope.frmUser["U_Name"].$setTouched(); 之后 $scope.frmUser["U_Name"].$invalid 始终保持真实。

只有当$scope.frmUser.$invalid 为假时,才会启用提交按钮

取而代之的是从 javascript 以编程方式设置每个字段的范围变量并将其设置为 true / false 工作正常。

【讨论】:

【参考方案5】:

如果你喜欢使用 ES6 + lodash fp

import forEach from 'lodash/fp/forEach'

    validate()
    
        forEach(forEach(field => field.$setTouched()))(this.form.$error)
    

<form name="$ctrl.form">...</form>

【讨论】:

【参考方案6】:

对于当前 v12 版本的 Angular,这些都是糟糕的答案。它可以简单地完成

submit() 
    this.form.markAllAsTouched();

【讨论】:

【参考方案7】:

我不确定您为什么认为必须“触摸”这些字段,只需使用常规表单验证;您只需将字段包装在实际的表单元素中,然后让 Angular 为您处理验证。 Here is a working example..

您真的不需要检查 $touched,甚至不需要设置它(除非有特定原因需要这样做?) - 如果输入字段是必填字段,只需在输入字段上使用 required 属性:

<input name="namefield" "text" ng-model="user.firstName" required/>

【讨论】:

因为有时您只希望在用户第一次尝试提交表单后应用错误样式并显示消息。我想这是大多数人都习惯的。 jQuery Validate 的行为也是如此。顺便说一句,我没有投票给你。 很公平。似乎有点反模式,允许用户执行您知道会失败的操作(允许他们在您进行客户端验证时点击提交),但每个人都有自己的 :) 例如,输入类型电子邮件的表单会因错误消息分散您的注意力,直到您输入的地址格式正确。如果他的输入最终有效,用户应该有机会正确填写表单。

以上是关于在提交表单时以编程方式将所有表单字段设置为 ng-touched的主要内容,如果未能解决你的问题,请参考以下文章

使用AngularJS提交时将空输入字段设置为ng-invalid?

提交表单将所有空输入及其关联的隐藏输入字段设置为禁用

使用 AngularJS 在表单提交时将选择字段重新设置为默认值

.reset()清除表单但不删除验证

触发 Angular 表单提交中所有字段的验证

无法在运行时以编程方式影响闪烁控制