【问题标题】:Input control in Angular: invalid input not detectedAngular 中的输入控制:未检测到无效输入
【发布时间】:2020-02-18 18:11:06
【问题描述】:

我正在为我的客户端应用程序使用 Angular 8。 当用户插入错误的输入时,我希望在用户的输入框下显示一条错误消息。我在我的 HTML 中使用它:

  <!-- Score input -->
  <div class="form-group">
    <label for="score">Score</label>
    <input type="number" class="form-control"
           placeholder="0.0 ÷ 10.0"
           min="0.0" max="10.0" step="0.1" name="score"
           id="score"
           [(ngModel)]="model.score"
           #score="ngModel">
    <div [hidden]="score.valid" class="alert alert-danger">
      Insert a value between 0.0 and 10.0
    </div>
  </div>

如果用户输入“asdf”而不是“6.7”之类的数字,我希望它会显示出来。但它永远不会出现。我尝试删除 [hidden]="score.valid" 并正确显示。即使我设置了所有这些属性,为什么 Angular 仍将“asdf”视为有效输入:type="number" min="0.0" max="10.0" step="0.1"

【问题讨论】:

  • 如果输入类型是数字,怎么可能输入字符串“asdf”?
  • @NicholasK 这是个好问题……我不知道!我会发图片,等等!
  • 您能否包含一个非常简单的堆栈闪电战,而不是发布一张图片进行复制?
  • @NicholasK:我相信这是设计使然。我可以在任何&lt;input&gt; 字段here 中输入文本。
  • 请看bug report 1398528。因此,例如,Chrome 不允许使用非数字字符,但 Firefox 允许。

标签: html angular validation


【解决方案1】:

数字类型的输入字段允许用户输入不属于数字的字符。详情请见here

我看不到您如何处理设置score.valid 变量的值。但是,它可以通过使用 CSS 伪类来实现。

input:invalid+span:after {
  content: 'Insert a value between 0.0 and 10.0';
  padding-left: 5px;
}
<!-- Score input -->
<div class="form-group">
  <label for="score">Score</label>
  <input id="input-validator" type="number" class="form-control"
         placeholder="0.0 ÷ 10.0"
         min="0.0" max="10.0" step="0.1" name="score"
         id="score"
         [(ngModel)]="model.score"
         #score="ngModel">
  <span class="alert alert-danger"></span>
</div>

更新:加入“提交”按钮。

模板:

<form  #scoreValue="ngForm" (ngSubmit)="submitScore(scoreValue.value)">

  <label>Score: </label>
  <input type="number" class="form-control" (keyup)="onKeyUp($event)" 
    placeholder="0.0 ÷ 10.0"
    [min]="min" [max]="max" [step]="step" name="score"
    id="score"
    [(ngModel)]="score"/>
  <span class="alert alert-danger"></span>
  <br /><br />
  <span> Does not work as expected -> </span>
  <button [disabled]="scoreValue.invalid">Submit</button>
  <br /><br />
  <span> Works as expected -> </span>
  <button [disabled]="disableSubmit">Submit</button>

</form>

组件:

public onKeyUp(event){
  let score = event.currentTarget.value;
  if ((score === '') || ((score.split('.')[1] || []).length > 1)) {
    this.disableSubmit = true;
  } else {
    score = Number(score);
    if ((score >= this.min) && (score <= this.max)) {
      this.disableSubmit = false;
    } else {
      this.disableSubmit = true;
    }
  }
}

工作示例:Stackblitz

minmax 属性仅设置步进箭头的最小值和最大值。这就是scoreValue.invalid 无法按预期工作的原因。

【讨论】:

  • 感谢您的回答!它工作得很好,但是我不知道如何禁用表单的“提交”按钮。在我检查表单是否有效之前:&lt;button class="btn btn-default" [disabled]="!feedbackForm.form.valid"&gt;Submit&lt;/button&gt;。用你的方法我该怎么做?
  • 再次感谢您的及时回复 :) 我目前正在使用您的代码作为参考。我注意到,如果我输入“8.7222”,错误消息会正确显示,但按钮没有被禁用。为什么?
  • 如果十进制值错误,我什至无法重现消息错误的正确显示(因为它在您的代码中有效)。你能用 cmets 强调这个约束是在哪里定义的吗?
  • "8.7222" 没有禁用按钮,因为我们没有检查小数部分的长度。我已经更新了代码,请看一下。特别是这部分:(score.split('.')[1] || []).length &gt; 1。如果小数部分的长度超过 1 则失败。
  • 我不确定为什么错误消息没有正确显示。目前我们使用constraint validation 来显示消息。我可以在主流浏览器(IE 除外)上对其进行测试。更多关于伪类的信息::invalid
【解决方案2】:

为什么让浏览器决定行为?
使用指令

<input appDecimalOnly />
/**
 * Credit: omeralper stackoverflow user
 * https://stackoverflow.com/questions/41465542/angular2-input-field-to-accept-only-numbers
 */
@Directive({
  selector: "[appDecimalOnly]"
})
export class DecimalOnlyDirective {
  constructor(private el: ElementRef) {}

  @HostListener("keydown", ["$event"]) onKeyDown(event) {
    let e = <KeyboardEvent>event;

    // console.log(e.keyCode)

    if (
      [46, 8, 9, 27, 13, 110, 190].indexOf(e.keyCode) !== -1 ||
      // Allow: Ctrl+A
      (e.keyCode === 65 && (e.ctrlKey || e.metaKey)) ||
      // Allow: Ctrl+C
      (e.keyCode === 67 && (e.ctrlKey || e.metaKey)) ||
      // Allow: Ctrl+V
      (e.keyCode === 86 && (e.ctrlKey || e.metaKey)) ||
      // Allow: Ctrl+X
      (e.keyCode === 88 && (e.ctrlKey || e.metaKey)) ||
      // Allow: home, end, left, right
      (e.keyCode >= 35 && e.keyCode <= 39)
    ) {
      // let it happen, don't do anything
      return;
    }
    // Ensure that it is a number and stop the keypress
    if (
      (e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) &&
      (e.keyCode < 96 || e.keyCode > 105)
    ) {
      e.preventDefault();
    }
  }
}

Stackblitz

【讨论】:

  • 真的做得很好!谢谢 :) 唯一的问题是这并不能阻止用户插入无效输入,例如12..99.0!我希望只允许x.y 类型的输入:)
  • @Robb1 很容易修复...stackblitz.com/edit/angular-cuyp6k
【解决方案3】:

为了更好的验证,你必须在 .ts 文件中使用 FormControl,你也可以看看官方文档https://angular.io/guide/form-validation

FormControl 比 ngModel 更灵活——值得一试:)

scoreControl = new FormControl('',
 Validators.compose([
   Validators.required,
   Validators.pattern('^[0-9]*$'),
   Validators.max(10)
 ])
);

并用它修改您的模板:

  <div class="form-group">
    <label for="score">Score</label>
    <input type="number" class="form-control"
           placeholder="0.0 ÷ 10.0"
           min="0.0" max="10.0" step="0.1" name="score"
           id="score"
           [formControl]="scoreControl">

    <div *ngIf="score.invalid" class="alert alert-danger">
      Insert a value between 0.0 and 10.0
    </div>

   </div>

仅关于数字输入,您可以在此处查看: https://stackoverflow.com/a/41479077/9178709

最好的方法是使用指令

【讨论】:

  • 感谢您的回答!不幸的是,使用您的方法,我仍然可以在输入中输入字符。也许这仍然与 Firefox 的错误有关?
  • 更新了我的分析器
猜你喜欢
  • 2019-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-25
  • 1970-01-01
  • 2021-06-30
  • 1970-01-01
  • 2020-03-19
相关资源
最近更新 更多