【问题标题】:How to validate start date and end date in angular?如何以角度验证开始日期和结束日期?
【发布时间】:2018-05-01 15:29:36
【问题描述】:

我正在以角度构建组件,我希望开始日期大于结束日期。我想知道我需要对我的 HTML 和 TS 代码进行哪些更改才能完成它。我使用的 HTML 和 TS 代码的 sn-ps 是:

HTML:

<form class="unavailability-form" [formGroup]="unavailabilityForm" *ngIf="loaded">
<div class="component-title" matDialogTitle>
   {{'PORTAL.TEXTUNAVAILABILITY' | translate}}
</div>
<mat-toolbar>
   <div class="container"
      fxLayout="row"
      fxLayout.xs="column"
      fxLayoutGap.xs="0">
      <div>
         <h1>{{componentTitle}}</h1>
      </div>
   </div>
</mat-toolbar>
<mat-dialog-content>
   <div class="container" fxLayout="row" fxLayout.xs="column" fxLayoutGap.xs="0" fxLayoutGap="10px">
      <div class="item item-1" fxFlex="50%" fxFlexOrder="1">
         <mat-form-field>
            <input matInput [matDatepicker]="picker" placeholder="{{'PORTALSTARTDATE' | translate}}"  type="text" formControlName="startDate" [(ngModel)]="availability.startDate" [readonly]="!componentPermission.writePermission">
            <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
            <mat-datepicker #picker></mat-datepicker>
         </mat-form-field>
      </div>
      <div class="item item-2" fxFlex="50%" fxFlexOrder="1">
         <mat-form-field>
            <input matInput [matDatepicker]="picker" placeholder="{{'PORTAL.ENDDATE' | translate}}"  type="text" formControlName="endDate" [(ngModel)]="availability.endDate" [readonly]="!componentPermission.writePermission">
            <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
            <mat-datepicker #picker></mat-datepicker>
         </mat-form-field>
      </div>
   </div>
   <div class="item item-1" fxFlex="50%" fxFlexOrder="1">
      <mat-form-field>
         <input matInput placeholder="{{'PORTAL.UNAVAILABILITYREASON' | translate}}" type="text" formControlName="unavailabilityReason" [(ngModel)]="availability.unavailabilityReason" [readonly]="!componentPermission.writePermission">
      </mat-form-field>
   </div>
</mat-dialog-content>
<mat-dialog-actions>
   <div class="container" fxLayout="row" fxLayout.xs="column" fxLayoutGap.xs="0">
      <div class="item item-1" fxFlex="100%">
         <button mat-raised-button color="primary" [disabled]="!locationForm.valid || !componentPermission.writePermission" (click)="onSave()">{{'PORTAL.CONFIRM' | translate}}</button>
         <button mat-raised-button [matDialogClose]="canceled" color="primary">{{'PORTAL.CANCEL' | translate}}</button>
      </div>
   </div>
</mat-dialog-actions>
</form>

TS:

  validateForm() {
    this.unavailabilityForm = this.formBuilder.group({
      'startDate': [''],
      'endDate': [''],
      'unavailabilityReason': ['']
    });
  }

在上面的代码中,{{PORTAL.___}} 文本是指数据库中的值。

【问题讨论】:

    标签: angular validation date


    【解决方案1】:

    请注意,您不能在表单中使用ngModel。您必须使用数据从组件中提供表单。这是删除ngModel的表格:

    <mat-dialog-content>
       <form [formGroup]="unavailabilityForm " novalidate fxFlex>
          <div class="container" fxLayout="row" fxLayout.xs="column" fxLayoutGap.xs="0" fxLayoutGap="10px">
             <div class="item item-1" fxFlex="50%" fxFlexOrder="1">
                <mat-form-field>
                   <input matInput [matDatepicker]="picker" placeholder="{{'PORTALSTARTDATE' | translate}}"  type="text" formControlName="startDate" [readonly]="!componentPermission.writePermission">
                   <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
                   <mat-datepicker #picker></mat-datepicker>
                </mat-form-field>
             </div>
             <div class="item item-2" fxFlex="50%" fxFlexOrder="1">
                <mat-form-field>
                   <input matInput [matDatepicker]="picker" placeholder="{{'PORTAL.ENDDATE' | translate}}"  type="text" formControlName="endDate" [readonly]="!componentPermission.writePermission">
                   <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
                   <mat-datepicker #picker></mat-datepicker>
                </mat-form-field>
             </div>
          </div>
          <div class="item item-1" fxFlex="50%" fxFlexOrder="1">
             <mat-form-field>
                <input matInput placeholder="{{'PORTAL.UNAVAILABILITYREASON' | translate}}" type="text" formControlName="unavailabilityReason"  [readonly]="!componentPermission.writePermission">
             </mat-form-field>
          </div>
       </form>
    </mat-dialog-content>
    

    然后您需要初始化表单并将 FormGroup 级别的验证器添加到您的组。我还向您的表单提供数据:

    initForm() {
        this.unavailabilityForm = this.formBuilder.group({
          'startDate': [availability.startDate],
          'endDate': [availability.endDate],
          'unavailabilityReason': [availability.unavailabilityReason]
        }, validateDate);
      }
    

    FormGroup 中的自定义验证器函数将是 validateDate

    自定义验证器函数应该是这样的:

    function validateDate(group: FormGroup) {
      ///TODO: Implement some better validation logic
      const invalid = group.get('startDate').value > group.get('endDate').value;
    
      ///TODO: Implement some logic to mark controls dirty if is necessary.
    
      return invalid ? { 'invalidDate': true } : null;
    }
    

    FormGroup 级别的自定义验证器中,您可以访问该组的所有控件并执行验证。请注意,表单的值将是字符串,因此,如果您使用 Date,则需要更好的逻辑来比较日期。

    另外请注意,组级验证器可能不会显示验证反馈,因此如果有必要,您需要手动将控件标记为脏。

    【讨论】:

    • 您不能合并ngModelformControlName。我的意思是你不能在FormGroup 中包含ngModel。你有哪些具体问题?您必须使用 formControlName 与 HTML 控件进行数据绑定。
    • 这里我使用 ngModel 来绑定来自打字稿的数据。错了吗?
    • 是的,这是错误的。您正在使用模型驱动的表单。这意味着您的模型将驱动表单,表单将更新 HTML。你需要实现它。查看更新。
    【解决方案2】:

    对于反应式表单,我是这样做的。

      deploymentSignOffDatesValidator(g: FormGroup) {
          return g.get('dateOfSignOff').value > g.get('dateOfDeployment').value ? null : {'unsequencial': true};
        }
    
      createEditUserForm(item: SaveUser) {
        if (!item) {
          item = {
            dateOfDeployment: '',
            dateOfSignOff: '',
          }
        }
    this.userEditForm = this.fb.group({
          dateOfDeployment: [item.dateOfDeployment, Validators.required],
          dateOfSignOff: [item.dateOfSignOff]
        }, {validator: this.deploymentSignOffDatesValidator});
    
    <div class="col-xl-3 col-lg-6 col-md-12">
                                    <fieldset class="form-group">
                                        <label for="dateOfSignOff">Date of SignOff:</label>
                                        <input
                                            class="form-control"
                                            placeholder="Date of SignOff"
                                            bsDatepicker
                                            formControlName="dateOfSignOff"
                                            [bsConfig]="{ dateInputFormat: 'YYYY-MM-DD', containerClass: 'theme-dark-blue' }"
                                            [ngClass]="{'is-invalid': userEditForm.get('dateOfSignOff').errors && (formDir.submitted || userEditForm.get('dateOfSignOff').touched) || userEditForm.hasError('unsequencial') && userEditForm.get('dateOfSignOff').touched}">
                                            <div class="" *ngIf="userEditForm.hasError('unsequencial') && userEditForm.get('dateOfSignOff').touched">The Deploymnet Date must be less than Sign Off Date</div>
                                    </fieldset>                                
                                </div>
    

    【讨论】:

      【解决方案3】:

      你可以查看我的库 ng-swiss-army-knife,里面有这个表单验证器(以及许多其他有用的 javascript/typescript/angular 的东西) https://github.com/nickwinger/ng-swiss-army-knife

      【讨论】:

      猜你喜欢
      • 2020-09-20
      • 2020-07-13
      • 2015-09-29
      • 1970-01-01
      • 1970-01-01
      • 2011-12-05
      • 1970-01-01
      • 1970-01-01
      • 2018-01-31
      相关资源
      最近更新 更多