Angular 2表单验证开始日期<=结束日期

问题描述 投票:6回答:6

我正在尝试添加验证,以便结束日期不能在开始日期之前。不幸的是我不知道该怎么做,到目前为止我在互联网上找不到任何有用的建议。我的表单看起来像这样:

editAndUpdateForm(tageler: Tageler) {
    this.tageler = tageler;
    this.tagelerForm = this.fb.group({
      title: [this.tageler.title, Validators.required],
      text: this.tageler.text,
      group: [[this.tageler.group], Validators.required],
      date_start: new Date(this.tageler.start).toISOString().slice(0, 10),
      date_end: new Date(this.tageler.end).toISOString().slice(0, 10),
      ...
    });
    this.tagelerForm.valueChanges
       .subscribe(data => this.onValueChanged(data));
    }

到目前为止我的验证:

onValueChanged(data?: any) {
    if (!this.tagelerForm) {
      return;
    }
    const form = this.tagelerForm;

    for (const field in this.formErrors) {

    // clear previous error message (if any)
      this.formErrors[field] = '';
      const control = form.get(field);

      if (control && control.dirty && !control.valid) {
        const messages = this.validationMessages[field];
        for (const key in control.errors) {
          this.formErrors[field] += messages[key] + ' ';
        }
      }
    }
}

validationMessages = {
    'title': {
      'required': 'Geben Sie bitte einen Namen ein.',
    },
    'group': {
      'required': 'Wählen Sie bitte eine Gruppe aus.'
    },
    'bringAlong': {
      'required': 'Bitte Feld ausfüllen.'
    },
    'uniform': {
      'required': 'Bitte Feld ausfüllen.'
    },
};

formErrors = {
    'title': 'Geben Sie bitte einen Namen ein.',
    'group': 'Wählen Sie bitte eine Gruppe aus.',
    'bringAlong': 'Bitte Feld ausfüllen',
    'uniform': 'Bitte Feld ausfüllen',
};

表单控件'date_start'和'date_end'包含一个'dd.MM.yyyy'形式的日期字符串,我希望'date_end'大于或等于'date_start'。

我想直接显示错误消息(我的HTML代码看起来像这样:)

<label for="formControlName_date_end" class="col-3 col-form-label">Ende:</label>
      <div class="col-5">
        <input id="formControlName_date_end" class="form-control" formControlName="date_end" type="date" value="{{tageler.end | date: 'yyyy-MM-dd'}}">
      </div>
      <div *ngIf="formErrors.date_end" class="alert alert-danger">
        {{ formErrors.date_end }}
      </div>

有人能帮助我吗?

谢谢!

validation angular2-forms
6个回答
2
投票

我们无法在验证中执行此操作,因为我们需要两个控制值startdate和enddate进行比较。因此,最好比较组件中的两个日期

error:any={isError:false,errorMessage:''};

compareTwoDates(){
   if(new Date(this.form.controls['date_end'].value)<new Date(this.form.controls['date_start'].value)){
      this.error={isError:true,errorMessage:'End Date can't before start date'};
   }
}

在你的HTML中

<label for="formControlName_date_end" class="col-3 col-form-label">Ende:</label>
<div class="col-5">
      <input id="formControlName_date_end" class="form-control" formControlName="date_end" type="date" value="{{tageler.end | date: 'yyyy-MM-dd'}}" (blur)="compareTwoDates()">
</div>
<div *ngIf="error.isError" class="alert alert-danger">
   {{ error.errorMessage }}
</div>

25
投票

基于santiagomaldonado的答案,我创建了一个通用的ValidatorFn,可以在具有动态返回值的多个Reactive Forms中使用。

export class DateValidators {
    static dateLessThan(dateField1: string, dateField2: string, validatorField: { [key: string]: boolean }): ValidatorFn {
        return (c: AbstractControl): { [key: string]: boolean } | null => {
            const date1 = c.get(dateField1).value;
            const date2 = c.get(dateField2).value;
            if ((date1 !== null && date2 !== null) && date1 > date2) {
                return validatorField;
            }
            return null;
        };
    }
}

导入验证器并在表格组验证器中使用它。

    this.form = this.fb.group({
        loadDate: null,
        deliveryDate: null,
    }, { validator: Validators.compose([
        DateValidators.dateLessThan('loadDate', 'deliveryDate', { 'loaddate': true }),
        DateValidators.dateLessThan('cargoLoadDate', 'cargoDeliveryDate', { 'cargoloaddate': true })
    ])});

现在您可以在HTML中使用验证。

<md-error *ngIf="form.hasError('loaddate')">Load date must be before delivery date</md-error>

11
投票

您也可以使用Reactive Forms执行此操作。 FormBuilder API允许您添加自定义验证器。

额外参数映射的有效键是validator和asyncValidator

例:

import { Component }  from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';

@Component({
  selector: 'reactive-form',
  templateUrl: './reactive-form.html'
})
export class ReactiveFormComponent {

  form: FormGroup

  constructor(private fb: FormBuilder){
    this.createForm();
  }

  createForm() {
    this.form = this.fb.group({
      dateTo: ['', Validators.required ],
      dateFrom: ['', Validators.required ]
    }, {validator: this.dateLessThan('dateFrom', 'dateTo')});
  }

  dateLessThan(from: string, to: string) {
   return (group: FormGroup): {[key: string]: any} => {
    let f = group.controls[from];
    let t = group.controls[to];
    if (f.value > t.value) {
      return {
        dates: "Date from should be less than Date to"
      };
    }
    return {};
   }
 }

}

请注意,我正在比较输入日期和来自>的值,但默认情况下这将是比较字符串。在实例中我使用angular-date-value-accessor并导入指令useValueAsDate。

<input formControlName="dateFrom" type="date" useValueAsDate />

使用此指令group.controls [from] .value和group.controls [to] .value返回Date,然后我可以将它们与<进行比较。

Live example in plunkr

积分兑换Dave's answer


1
投票

创建一个表单组。让控件成为表单组的一部分。

       new FormGroup({   
        startDate: this.fb.group({
            dateInput: [{value: ""}, startDateValidator()]
        }),   
        endDate: this.fb.group({
            dateInput: ["", endDateValidator()]
        })  
    }, startDateCannotBeLessThanEndDateValidator());   

        startDateCannotBeLessThanEndDateValidator(formGroup: FormGroup) {

             let startDate = formGroup.get("startDate");   
            let endDate = formGroup.get("endDate");
            // compare 2 dates 
        }

0
投票

我正在使用时刻,并在角度7比较和验证日期,我使用此功能:

datesValidator(date1: any, date2: any): {[key:string]:any} | null {
    return (group: FormGroup): { [key: string]: any } | null => {
        let start = group.controls[date1].value;
        let end = group.controls[date2].value;
        let datum1 = _moment(start).startOf('day');
        let datum2 = _moment(end).startOf('day');
        if (_moment(datum1).isSameOrAfter(datum2)) {
           this.alert.red("Error: wrong period!"); //popup message
           return { 'error': 'Wrong period!' };        
        }
        return null; //period is ok, return null
    };
}

0
投票

我的是angular7 + ngprime(日历)

(*如果您不希望ngprime只是将日历部分替换为其他人。)

请参阅以下代码进行日期验证。

我的代码有额外的验证,一旦选择了开始日期,我会阻止结束数据日历中的前几天,以便结束日期总是晚于此。

如果您不想阻止日期,请删除[minDate]部分。它也在工作。

>组件

export class test implements OnInit {

  constructor() { }

  defaultDate: Date = new Date();
  checkDate = true;
  form: FormGroup;

  today: Date = new Date(); //StartDate for startDatetime
  startDate: Date = new Date();  //StartDate for endDatetime

  initFormControls(): void {
    this.today.setDate(this.today.getDate());
    this.startDate.setDate(this.today.getDate()); //or start date + 1 day

    this.form = new FormGroup({
      startDatetime: new FormControl('', [Validators.required]),
      endDatetime: new FormControl('', [Validators.required])
    },
      { validators: this.checkDateValidation });
  }

  checkDateValidation: ValidatorFn = (control: FormGroup): ValidationErrors | null => {
    try {

      let startingDatefield = control.get('startDatetime').value;

      this.startDate = new Date(startingDatefield); //new Date(startingDatefield).getDate()
      let endingDatefield = control.get('endDatetime').value;

      if (this.today >= startingDatefield) { //compare to current date 
        console.log("Please set a Start Date that is on or after Current Date and Time.");
        return { 'effectiveStartDatetime': false };

      } else
        if (startingDatefield > endingDatefield && endingDatefield) {
          console.log("Please set an End Date and Time that is after the Start Date and Time.");
          return {};

        } else {
          return {};
        }
    } catch (err) {
    }
  };



  onSubmit() {

    //if form is not valid
    if (!this.form.valid) {
      console.log(" Please fill in all the mandatory fields");

      // do sth
    return;
    }


    //if form is valid
    //do sth

  }


  ngOnInit() {
    this.initFormControls();
  }

> HTML

<form [formGroup]="form" (ngSubmit)="onSubmit()">
  <div>
    <div>
      <p-button type="submit" label="submit"></p-button>
    </div>
  </div>
  <div>
    <p>Start Date/Time"</p>
    <div>
      <p-calendar formControlName="startDatetime" appendTo="body" showTime="true" hourFormat="24" stepMinute="30"
        showSeconds="false" dateFormat="yy-mm-dd" [minDate]="today"></p-calendar>
      <div
        *ngIf="form.get('startDatetime').invalid && (form.get('startDatetime').dirty || form.get('startDatetime').touched)">
        <div *ngIf="form.get('startDatetime').hasError('required')">
        </div>
      </div>
    </div>

    <p>End Date/Time</p>
    <div>
      <p-calendar formControlName="endDatetime" appendTo="body" showTime="true" hourFormat="24" stepMinute="30"
        showSeconds="false" dateFormat="yy-mm-dd" [minDate]="startDate"></p-calendar>
      <div *ngIf="form.get('endDatetime').invalid && (form.get('endDatetime').dirty || form.get('endDatetime').touched)">
        <div *ngIf="!checkDate || form.get('endDatetime').hasError('required')">
        </div>
      </div>
    </div>
  </div>

</form>
© www.soinside.com 2019 - 2024. All rights reserved.