Angular 2 form validations start date <= end date

前端 未结 6 1999
孤街浪徒
孤街浪徒 2020-12-09 05:01

I\'m trying to add validations such that the end date can\'t be before the start date. Unfortunately I have no idea how to do that, and I didn\'t find any helpful advice in

相关标签:
6条回答
  • 2020-12-09 05:16

    You can also do it with Reactive Forms. The FormBuilder API lets you add custom validators.

    Valid keys for the extra parameter map are validator and asyncValidator

    Example:

    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 {};
       }
     }
    
    }
    

    Note that I'm comparing the values of the inputs date and from with >, but by default this would be comparing strings. In the live example I'm using angular-date-value-accessor and importing the directive useValueAsDate.

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

    With this directive group.controls[from].value and group.controls[to].value returns Date and then I can compare them with <.

    Live example in plunkr

    Credits to Dave's answer

    0 讨论(0)
  • 2020-12-09 05:16

    create a form group . Let the controls be a part of form group .

           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 讨论(0)
  • 2020-12-09 05:18

    I am using moment, and in angular 7 to compare and validate dates, i use this function:

    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 讨论(0)
  • 2020-12-09 05:20

    Based on the answer of santiagomaldonado I have created a generic ValidatorFn that can be used in multiple Reactive Forms with a dynamic return value.

    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;
            };
        }
    }
    

    Import the validator and use it like this in your formgroup validators.

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

    Now you can use the validation in HTML.

    <md-error *ngIf="form.hasError('loaddate')">Load date must be before delivery date</md-error>
    
    0 讨论(0)
  • 2020-12-09 05:22

    we cant do it in validation because we need two control values that is startdate and enddate for comparison. So it is better to compare two dates in your component

    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'};
       }
    }
    

    In your 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>
    
    0 讨论(0)
  • 2020-12-09 05:35

    Mine is angular7 + ngprime(for calendar)

    (*if you don't want ngprime just replace calendar part to others.)

    Refer below code for date validation.

    My code has additional validation that once start date is selected, I block previous days in end data's calendar so that the end date will be always later than that.

    if you don't want to block date, delete [minDate] part. it is also working.

    > Component

    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>
    
    0 讨论(0)
提交回复
热议问题