Angular会自动在“required”字段上添加“ng-invalid”类

45

我正在构建一个Angular应用程序,其中有一些表单已经设置好了。在提交之前,需要填写一些必填字段。因此,我已经在它们上面添加了'required'属性:

<input type="text" class="form-control" placeholder="Test" ng-model="data.test" required>

然而,当我启动应用程序时,即使在用户未单击提交按钮或在字段中键入任何内容之前,这些字段也显示为“无效”,并且类“ng-invalid”和“ng-invalid-required”已经添加。

我该如何确保这两个类不是立即添加的,而是在用户提交表单或在相应字段中输入错误后再添加?

5个回答

92

由于输入为空并且在实例化时无效,Angular会正确地添加 ng-invalid 类。

您可以尝试使用的 CSS 规则:

input.ng-dirty.ng-invalid {
  color: red
}

基本上,这句话的意思是:当某个字段自页面加载以来曾经有过输入,且没有通过$scope.formName.setPristine(true)被还原为初始状态,且目前该字段仍然未填入任何内容却无效时,文本会变成红色

Angular表单的其他实用类(有关详细信息,请参见input):

ng-valid-maxlength - 当ng-maxlength通过验证时
ng-valid-minlength - 当ng-minlength通过验证时
ng-valid-pattern - 当ng-pattern通过验证时
ng-dirty - 当表单从加载以来已输入了一些内容时
ng-pristine - 当表单输入框自加载以来尚未插入任何内容(或通过表单上的setPristine(true)重置)时
ng-invalid - 当任何验证失败时(例如: required, minlength,自定义验证等)

同样地,对于所有这些模式和任何自定义模式,也可以使用ng-invalid-<name>


4
使用屏幕阅读器(我使用的是NVDA屏幕阅读器)时会出现问题——一旦聚焦到该字段,它会大声喊出“无效输入”。 - Kumar Sambhav
这很有趣,针对屏幕阅读器的库马尔。我很好奇,这是因为 Angular 的控制器验证设置还是因为输入框上的简单红色? - Ryan Q
你好,你的修复方法有问题。因为用户不依赖CSS来提交表单或者不提交表单,所以开发人员必须在将结果发送到任何地方之前进行检查,或者在每个输入上设置一个布尔值(modelchange)。 - user10201743

8
感谢本文,我使用这种样式来去除Bootstrap自动显示的红色边框,当显示必需字段时,用户还没有机会输入任何内容:
input.ng-pristine.ng-invalid {
    -webkit-box-shadow: none;
    -ms-box-shadow: none;
    box-shadow:none;
}

2

由于这些字段为空,它们是无效的,因此会正确添加ng-invalidng-invalid-required类。

您可以使用ng-pristine类来检查字段是否已经被使用过。


教程链接已失效。 - Max
感谢您的评论。您可以从这里部署 ng-tutorial https://github.com/mgechev/ng-tutorial - Minko Gechev
我认为问题不在于对错,而在于用户体验。默认情况下Angular设置表单全部为红色是一种可怕的体验。初始状态是否无效?是的。但是展示全部为红色是否友好?不是的。 - Tiago B

1
以下方法适用于旧版 AngularJS:
尝试在表单提交或字段无效时动态添加验证类。使用表单名称并将'name'属性添加到输入框中。示例使用Bootstrap:
<div class="form-group" ng-class="{'has-error': myForm.$submitted && (myForm.username.$invalid && !myForm.username.$pristine)}">
    <label class="col-sm-2 control-label" for="username">Username*</label>
    <div class="col-sm-10 col-md-9">
        <input ng-model="data.username" id="username" name="username" type="text" class="form-control input-md" required>
    </div>
</div>

同样重要的是,您的表单具有ng-submit=""属性:

<form name="myForm" ng-submit="checkSubmit()" novalidate>
 <!-- input fields here -->
 ....

  <button type="submit">Submit</button>
</form>

您还可以为表单添加一个可选的验证功能:
//within your controller (some extras...)

$scope.checkSubmit = function () {

   if ($scope.myForm.$valid) {
        alert('All good...'); //next step!
          
   }
   else {
        alert('Not all fields valid! Do something...');
    }

 }

现在,当您加载应用程序时,只有在表单提交或字段被触摸时才会添加类名为'has-error'的元素。 而不是:
!myForm.username.$pristine

您也可以使用:
myForm.username.$dirty

适用于新的Angular 2+

这基于Bootstrap 5.3和Angular 15/16,可能会在将来发生变化。

<div class="form-group">
  <label>Password</label>
  <input type="password" formControlName="password" class="form-control" [ngClass]="{'is-invalid': password?.errors != null}">
</div>

组件形式,请确保您已将myForm更改为所需的表单变量。

  get password() { return this.myForm.get("password") }

-2

被接受的答案是正确的.. 对于移动设备,您还可以使用这个(ng-touched 而不是 ng-dirty)

input.ng-invalid.ng-touched{
  border-bottom: 1px solid #e74c3c !important; 
}

7
ng-touched类表示该字段已失去焦点,与移动设备无关。 - jrista

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接