【问题标题】:Date and Currency validation in Angular (4)Angular 中的日期和货币验证 (4)
【发布时间】:2018-03-17 07:45:19
【问题描述】:

我是 Angular 的新手。我正在使用 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]],

我正在尝试了解如何执行货币(带或不带两位小数)以及最重要的日期字段。

如果这在其他地方得到了回答,请原谅我,但我找不到 angular(4) 的任何样本

感谢您的宝贵时间

【问题讨论】:

  • 为什么不使用 CurrencyPipe? angular.io/api/common/CurrencyPipe
  • 感谢您的建议。如果我错了,请纠正我。货币管道用于转换显示值正确吗?我正在寻找文本框输入的验证。
  • 我的坏!你是对的!

标签: angular typescript angular-forms


【解决方案1】:

您需要什么样的日期验证?只是该值是有效日期吗?如果您在输入元素上设置type="date",浏览器将确保仅输入有效日期。

对于您显示的数字验证器和任何货币验证器都是如此。您应该能够在输入元素上设置type="number",并且不需要验证器。

如果您仍然确实想要执行自己的验证,您可以使用正则表达式,就像在您的示例中一样。

只需查找货币和日期的正则表达式。对于日期,类似这样:Javascript - Regex to validate date format

【讨论】:

  • 感谢您的回复。设置 type="date" 是否适用于所有浏览器或仅支持 html 5 的浏览器。为了更安全,我想在组件方面进行自己的验证。所以你推荐正则表达式进行自定义验证?谢谢
  • 这就是您在此处的示例中所做的:(c.value.match(/.*[^0-9].*/)) 所以我假设您想要类似的东西?您可以使用以下方法确定哪些浏览器支持特定功能:caniuse.com/#search=type%3D%22date%22
  • 感谢您的回复。
  • 如果您可以将此标记为答案,我们可以关闭此问题。谢谢!
  • input type = "date" IE11及更早版本不支持!
【解决方案2】:

创建了一个自定义验证器来处理格式 MM/DD/YYYY 和 MMDDYYYY

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

【讨论】:

    【解决方案3】:

    这是使用自定义验证器的另一种选择

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

    并以这种方式将其用于“dd/mm/yyyy”格式:

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

    并以这种方式将其用于“mm/dd/yyyy”格式:

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

    希望对你有所帮助!

    【讨论】:

    • 我们在 app.module.ts 等的哪里添加这个?
    • @MaxRocket 验证器只是函数。您不会将它们添加到您的模块中。只需导入它们:import { checkDateMethod } from './check-date.validator'; 并直接使用它们而不调用此函数:new FormControl(null, { asyncValidators: [checkDateMethod] })
    • 这个解决方案对我来说效果很好,我所做的唯一改变是检查空值。喜欢if (control.value &amp;&amp; !control.value.match(ptDatePattern)) return { "ptDate": true };。否则,如果启动像:date: [null, [Validators.required, DateValidator.usDate]] 这样的字段,它会立即抛出一个空异常。
    【解决方案4】:

    这是我的解决方案:

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

    【讨论】:

    • 这个怎么用?我在哪里把它放在 app.module.ts 中?谢谢
    • 你可以放入任何.ts文件。我有一个名为 my-validators.ts 的文件,我在需要它的地方引用它
    【解决方案5】:

    如果您使用 Angular Material,您可以使用 MatDatepicker 与 Moment.js 的集成来使用 FormControl 验证自定义日期格式,如下所示:

    https://material.angular.io/components/datepicker/overview#customizing-the-parse-and-display-formats

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

    【讨论】:

      【解决方案6】:

      如果您使用的是响应式表单,您可以编写自定义验证器,见下文

      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]],
        })
      

      【讨论】:

        【解决方案7】:

        这是(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;
        }
        

        【讨论】:

          【解决方案8】:

          此解决方案对我有用,并且满足以下条件


          1. 开始日期
          2. 开始日期 >= 今天
          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');
            }
          
            }
          

          日期验证器.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 {};
          }
          

          【讨论】:

            【解决方案9】:

            Angular ma​​t-datepickerma​​tDatepickerParse 添加到无法解析输入字符串的表单控件错误对象

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-12-17
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多