Проверка даты и валюты в Angular (4)

Я новичок в Angular. Я использую угловые 4 реактивные формы и выяснил, как выполнить пользовательские проверки. Следующее - моя реализация для числового

function numberValidator(c: AbstractControl): { [key: string]: boolean } | null {
    if (c.pristine) {
        return null;
    }
    if (c.value.match(/.*[^0-9].*/)) {
        return { 'numeric': true };
    }
    return null;
}

 phoneControl: ['', [Validators.required, Validators.minLength(10), Validators.maxLength(10), numberValidator]],

Я пытаюсь выяснить, как выполнить валюту (с двумя десятичными знаками или без них) и, самое главное, поле "Дата".

Простите, если на этот вопрос ответили в другом месте, но я не могу найти образцы для угловых (4)

Спасибо за ваше время

3 ответа

Решение

Какой тип проверки даты вам нужен? Просто значение является действительной датой? Если вы установите type="date" на элементе ввода браузер обеспечит ввод только действительной даты.

То же самое для вашего показанного валидатора номера и для любого валидатора валюты. Вы должны быть в состоянии установить type="number" на элементе ввода, и вам не понадобится валидатор.

Если вы все еще хотите выполнить свою собственную проверку, вы можете использовать регулярные выражения, как в вашем примере.

Просто найдите регулярные выражения для валюты и даты. Для даты, что-то вроде этого: Javascript - Regex для проверки формата даты

Это еще один вариант использования пользовательских валидаторов

import { FormControl } from '@angular/forms';

export class DateValidator {

   static ptDate(control: FormControl): { [key: string]: any } {
       let ptDatePattern =  /^(((0[1-9]|[12]\d|3[01])\/(0[13578]|1[02])\/((19|[2-9]\d)\d{2}))|((0[1-9]|[12]\d|30)\/(0[13456789]|1[012])\/((19|[2-9]\d)\d{2}))|((0[1-9]|1\d|2[0-8])\/02\/((19|[2-9]\d)\d{2}))|(29\/02\/((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$/g;

       if (!control.value.match(ptDatePattern))
           return { "ptDate": true };

       return null;
   }

   static usDate(control: FormControl): { [key: string]: any } {
       let usDatePattern = /^02\/(?:[01]\d|2\d)\/(?:19|20)(?:0[048]|[13579][26]|[2468][048])|(?:0[13578]|10|12)\/(?:[0-2]\d|3[01])\/(?:19|20)\d{2}|(?:0[469]|11)\/(?:[0-2]\d|30)\/(?:19|20)\d{2}|02\/(?:[0-1]\d|2[0-8])\/(?:19|20)\d{2}$/;

       if (!control.value.match(usDatePattern))
           return { "usDate": true };

       return null;
   }
}

и используйте его таким образом для формата "дд / мм / гггг":

this.formDetail = this.formBuilder.group({
   date: ['', DateValidator.ptDate],
});

и используйте его таким образом для формата "мм ​​/ дд / гггг":

this.formDetail = this.formBuilder.group({
   date: ['', DateValidator.usDate],
});

Я надеюсь, что это поможет!

Если вы используете реактивные формы, вы можете написать собственный валидатор, см. Ниже

dateValidator(c: AbstractControl): { [key: string]: boolean } {
    let value = c.value;
    if (value && typeof value === "string") {
      let match = value.match(/^([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))/);
      if (!match) {
        return { 'dateInvalid': true };
      } else if (match && match[0] !== value) {
        return { 'dateInvalid': true };
      }
    }
    return null;
  }

При создании элемента управления вам необходимо добавить этот валидатор вместе с другими валидаторами, как показано ниже.

const group = this.fb.group({
    DateType: ['', [Validators.required, this.dateValidator]],
  })

Создан пользовательский валидатор для обработки форматов ММ / ДД / ГГГГ и ММДДГГГГ

function dateValidator(c: AbstractControl): { [key: string]: boolean } | null {
    if (c.pristine) {
        return null;
    }
    if ((c.value !== undefined && c.value !== '' && c.value != null)) {

        var month = null;
        var day = null;
        var year = null;
        var currentTaxYear = Number(new Date().getFullYear() - 1);
        if (c.value.indexOf('/') > -1) {
            var res = c.value.split("/");           
            if (res.length > 1) {
                month = res[0];
                day = res[1]
                year = res[2];
            }                              
        }
        else {
            if (c.value.length == 8) {
                month = c.value.substring(0, 2);
                day = c.value.substring(2, 4);
                year = c.value.substring(4, 8);
            }            
        }
        if (isNaN(month) || isNaN(day) || isNaN(year)) {
            return { 'dateInvalid': true };
        } 
        month = Number(month);
        day = Number(day);
        year = Number(year);
        if (month < 1 || month > 12) { // check month range
            return { 'dateInvalid': true };
        }
        if (day < 1 || day > 31) {
            return { 'dateInvalid': true };
        }
        if ((month === 4 || month === 6 || month === 9 || month === 11) && day === 31) {
            return { 'dateInvalid': true };
        }
        if (month == 2) { // check for february 29th
            var isleap = (year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0));
            if (day > 29 || (day === 29 && !isleap)) {
                return { 'dateInvalid': true };
            }
        }
        if (year !== currentTaxYear) {
            return { 'dateYearGreaterThanTaxYear': true };
        }
    }
    return null;
}

Это решение сработало для меня, и следующие довольны


  1. startDate
  2. startDate> = сегодня
  3. endDate >= сегодня

app.component.html

<form [formGroup]="addContract>
 <div class="form-group">
              <label>Start Date *</label>
              <input type="date" name="startDate" formControlName="startDate" 
               class="form-control" placeholder="Arrival *"
               [ngClass]="{ 'is-invalid': submitted && f.startDate.errors}"/>
              <div *ngIf="f.startDate.touched">
                <small *ngIf="f.startDate.errors?.required"                    
                 class="text-danger">Required</small>
                <small *ngIf="addContract.errors?.invaineFrom" class="text-danger">  
                 Select a date Over today</small>
              </div>
    </div>

<div class="form-group">
              <label>End Date*</label>
              <input type="date" name="endDate" formControlName="endDate"
              class="form-control" placeholder="Departure *"
              [class.is-invalid]="endDate.invalid && endDate.touched"/>

              <div *ngIf="f.endDate.touched">
                <small *ngIf="endDate.errors?.required && 
                 endDate.touched ">Required</small>
                <small *ngIf="addContract.errors?.invaineTo" class="text-danger">    
                 choose a date over today</small>
                <small *ngIf="addContract.errors?.dates" class="text-danger">
                End Date should be grater than start Date</small>
              </div>
              </div>
            
           
 </div>
</form>

app.component.ts

import { DateValidator} from '../shared/date-validator';


export class AppComponent implements OnInit {
  addContract: FormGroup;
  ngOnInit() {
    this.addContract = this.fb.group({
      startDate: ['', [Validators.required]],
      endDate: ['', [Validators.required]]
    }, {validator: DateValidator});


  get f() { return this.addContract.controls; }

  get endDate() {
    return this.addContract.get('endDate');
  }
  get startDate() {
    return this.addContract.get('startDate');
  }

  }

дата-validator.ts

import {AbstractControl} from '@angular/forms';

export function DateValidator(control: AbstractControl): { [ key: string]: boolean} | null { 



let from = control.get('startDate');
let to = control.get('endDate');
let c= new Date();
if(new Date(from.value)< c )
{
    return {
        invaineFrom:true
    }
}
if(new Date(to.value) < c )
{
    return {
        invaineTo:true
    }
}
if (from.value > to.value ) {
    return {
      dates: true
    };
  }
  return {};
}

Если вы используете Angular Material, вы можете использовать интеграцию MatDatepicker с Moment.js для проверки настраиваемого формата даты с помощью FormControl, как показано здесь:

https://material.angular.io/components/datepicker/overview

HTML:

<input matInput [matDatepicker]="dp" placeholder="Verbose datepicker" [formControl]="date">

TS:

export const MY_FORMATS = {
  parse: {
    dateInput: 'LL',
  },
  display: {
    dateInput: 'LL',
    monthYearLabel: 'MMM YYYY',
    dateA11yLabel: 'LL',
    monthYearA11yLabel: 'MMMM YYYY',
  },
};

@Component({
  selector: 'datepicker-formats-example',
  templateUrl: 'datepicker-formats-example.html',
  styleUrls: ['datepicker-formats-example.css'],
  providers: [
    {provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE]},
    {provide: MAT_DATE_FORMATS, useValue: MY_FORMATS},
  ],
})
export class DatepickerFormatsExample {
  date = new FormControl(moment());
}

Вот (imo) лучшая функция проверки даты:

function date(c: AbstractControl): { [key: string]: boolean } {
   let value = new Date(c.value);
   return isNaN(value.getTime()) || value <= new Date('01/01/1753') ? {'dateInvalid': true} : undefined;
}

Angular mat- datepicker добавляет matDatepickerParse к объекту ошибки управления формой, если он не может проанализировать входную строку

Это мое решение:

import {AbstractControl} from "@angular/forms";

export class MyValidators {

  // validate MM/DD/YYYY
  static date(c: AbstractControl): { [key: string]: boolean } {
    let value = c.value;
    if (value && typeof value === "string") {
      let match = value.match(/^([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{4})$/);
      if (!match) {
        return {'dateInvalid': true};
      }
      let date = new Date(`${match[3]}-${match[1]}-${match[2]}`);
      if (isNaN(date.getTime())) {
        return {'dateInvalid': true};
      }
    }
    return null;
  }

}
Другие вопросы по тегам