Angular 日期选择器 - 输入字段失去焦点的问题

问题描述 投票:0回答:1

我正在尝试对输入字段上的 (focusout) 事件的 Angular Material Date 选择器进行一些验证。如果在验证过程中发现问题,我会将焦点返回到 Mat Date Picker 输入字段。

同时,当用户选择日期选择器图标打开日期选择器弹出窗口时,我不希望调用验证。有没有办法避免在单击日期选择器图标时调用已完成的验证(焦点)。


<mat-form-field>
<mat-label> select dates </mat-label>
<input matInput [matDatepicker]="seldatepicker" [(ngModel)]="seldate" (focusout)="validateDate($event)">
<mat-hint>MM/DD/YYYY</mat-hint>
<mat-datepicker-toggle matSuffix [for]="seldatepicker"></mat-datepicker-toggle>
<mat-datepicker #seldatepicker></mat-datepicker>
</mat-form-field>

提前致谢。

我尝试使用 (dateChange) 事件来检查验证,但这并不能阻止在单击 Mat 日期选择器图标时对输入元素上的日期输入调用验证。

angular-material mat-datepicker
1个回答
0
投票

您可以使用

updateOn
配置的
ngModelOptions
属性并将其设置为仅在
blur
事件上验证。


如果上述建议没有帮助,那么您可以订阅

closedStream
,它会在日期选择器关闭时触发,然后使用
setTimeout
函数,我们会在延迟
500ms
后触发日期选择器打开方法。

ngAfterViewInit() {
  this.picker.closedStream.subscribe(() => {
    debugger;
    if (this.modelRef.invalid) {
      setTimeout(() => {
        this.picker.open();
      }, 500);
    }
  });
}

理想情况下,您应该将其放在指令中以提高代码的可重用性。

完整代码:

import { ChangeDetectionStrategy, Component, ViewChild } from '@angular/core';
import {
  MatDatepicker,
  MatDatepickerModule,
} from '@angular/material/datepicker';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { provideNativeDateAdapter } from '@angular/material/core';

import { Directive, Input, forwardRef } from '@angular/core';
import { JsonPipe } from '@angular/common';
import {
  NG_VALIDATORS,
  Validator,
  AbstractControl,
  ValidationErrors,
  FormsModule,
  NgModel,
} from '@angular/forms';

@Directive({
  selector: '[appCustomValidator]',
  standalone: true,
  providers: [
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => CustomValidatorDirective),
      multi: true,
    },
  ],
})
export class CustomValidatorDirective implements Validator {
  validate(control: AbstractControl): ValidationErrors | null {
    let today: Date = new Date();

    if (new Date(control.value) > today) return { LessThanToday: true };

    return null;
  }
}

/** @title Basic datepicker */
@Component({
  selector: 'datepicker-overview-example',
  templateUrl: 'datepicker-overview-example.html',
  standalone: true,
  providers: [provideNativeDateAdapter()],
  imports: [
    MatFormFieldModule,
    MatInputModule,
    MatDatepickerModule,
    FormsModule,
    JsonPipe,
    CustomValidatorDirective,
  ],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DatepickerOverviewExample {
  @ViewChild(NgModel) modelRef!: NgModel;
  @ViewChild(MatDatepicker) picker!: MatDatepicker<any>;
  selectedDate = new Date();

  ngAfterViewInit() {
    this.picker.closedStream.subscribe(() => {
      debugger;
      if (this.modelRef.invalid) {
        setTimeout(() => {
          this.picker.open();
        }, 500);
      }
    });
  }
}

Stackblitz 演示

© www.soinside.com 2019 - 2024. All rights reserved.