在 Angular 8 中手动将 select 字段设置为无效

set select field to invalid manually in Angular 8

我在 Angular 8 中有一个 select 字段绑定到一个按钮。我希望能够单击按钮,如果字段中没有 selected,我想让该字段无效。

这是我的 select 字段和按钮:

<div class="input-group-prepend">
       <button class="btn btn-primary" type="button" (click)="AddNewSchedule()>
          <i class="material-icons post_add" aria-hidden="true"></i>
       </button>
    </div>
    <select class="form-control"
      [(ngModel)]="ScheduleDataObj.modeOfTransportID"
      name="modeOfTransportID"
      #modeOfTransportID="ngModel"
      (change)="ModeValueChange($event)"
    >
      <option [value]="0">Select Mode</option>
      <option *ngFor="let m of Modes" [value]="m.modeOfTransportID">{{ m.mode }}</option>
    </select>

如何手动使字段无效?

这是我使用绑定到按钮的事件处理函数尝试过的:

@ViewChild('modeOfTransportID', { static: false }) modeID: HTMLFormElement;

public AddNewSchedule() {
 if (this.ScheduleDataObj.modeOfTransportID === 0) {
      this.modeID.setErrors({ invalid: true });
      return false;
    } else {
      this.modeID.setErrors(null);
   } 
}

单击按钮时出现错误 'setErrors is not a function'。我也试过 this.modeID.control.invalid = true 没用。

它应该是 NgModel 指令的类型,而不是 HTMLFormElement 和控件内部可用的 setError 方法 属性

试试这个:

   @ViewChild('modeOfTransportID', { static: false }) modeID: NgModel;
   public AddNewSchedule() {
    if (this.ScheduleDataObj.modeOfTransportID === 0) {
      this.modeID.control.setErrors({ invalid: true });
      return false;
    } else {
      this.modeID.control.setErrors(null);
    } 
  }

@Chellappan வ 的回答完全正确,但我想解决您的代码中的其他一些问题。首先,per the spec, value will always be of type string. So, this.ScheduleDataObj.modeOfTransportID === 0 will always be false because it needs to be === '0'. However, you can fix it using ngValue。来自文档(强调我的):

ngValue: Tracks the value bound to the option element. Unlike the value binding, ngValue supports binding to objects.

因此您可以重构您的视图以使用 ngValue 并且您的代码将起作用:

<select class="form-control"
  [(ngModel)]="ScheduleDataObj.modeOfTransportID"
  name="modeOfTransportID"
  #modeOfTransportID="ngModel"
  (change)="ModeValueChange($event)">
  <option [ngValue]="0">Select Mode</option>
  <option [ngValue]="1">Some Mode</option>
</select>

此外,与其考虑根据 html 事件观察值(这可能会变得棘手,因为您的模型值可能不会在您认为正确的时候准确更改),您可以将代码重构为观察 FormControl 本身的值变化。请务必等到视图初始化之后,这样您的 @ViewChild ref 就不会为 null:

ngAfterViewInit() {
  // Watch our modeID value changes.
  // Using takeUntil to avoid memory leaks.
  this.modeID.valueChanges
    .pipe(takeUntil(this.unsubscribe))
    .subscribe(value => {
      if (value === 0) {
        // Note: this will remove other validation errors. 
        // If that is not desired behavior, see this discussion:
        // https://github.com/angular/angular/issues/21564
        this.modeID.control.setErrors({ invalid: true });
      } else {
        // This also removes *all* errors, which might not
        // be desired behavior.
        this.modeID.control.setErrors(null);
      }
    });
}

综合起来,here's a working example on stackblitz. You also could easily just build a custom validator为了这个。