Feature: ngbDatePicker ngInvalid for Optional Field in Reactive Form

Feature description:

There’s no way to have a date field be optional when using ngbDatePicker it always indicates the field is ngInvalid. I tried setting the model to '', null, undefined. Empty string means ngInvalid will prevent it from being optional, and null/undefined works to make it optional, but it throws an error when null/undefined is split by formatDate.

private formatDate(date: string): { year: number, month: number, day: number } {
  const { 0: year, 1: month, 2: day } = date.split('-'); 
  return { year: parseInt(year, 10), month: parseInt(month, 10), day: parseInt(day, 10) };
}

Looks like this might just need a null check of some sort in formatDate, but it would be a better if it instead relied on Validations.required to be set by the developer instead so whether it is required is external to the directive making an empty string valid.

Example Form Model

this.form = this.formBuilder.group({
  id: [
    0, [Validators.required]
  ],

  // ... removed for brevity

  business_type: [
    '', [Validators.required]
  ],
  business_incorp_date: [
    '', [] // <-- OPTIONAL FIELD, but always ngInvalid on { "ngbDate": { "invalid": { "year": null, "month": null, "day": null } } }
  ],
  business_desc: [
    '', [Validators.required]
  ]

  // ...
});

Example Input

<input type="text"
        id="business_incorp_date"
        class="form-control"
        formControlName="business_incorp_date"
        ngbDatepicker
        #incorporatedDatePicker="ngbDatepicker"
        (click)="incorporatedDatePicker.toggle()"
        readonly>

Version of Angular, ng-bootstrap, and Bootstrap:

Angular: 4.1.1

ng-bootstrap: ^1.0.0-alpha.25

Bootstrap: 4.0.0-alpha.6

3 thoughts on “Feature: ngbDatePicker ngInvalid for Optional Field in Reactive Form

  1. It is because you are initialising it to an empty string here:

    business_incorp_date: [
        '', [] // <-- OPTIONAL FIELD, but always ngInvalid on { "ngbDate": { "invalid": { "year": null, "month": null, "day": null } } }
      ]
    

    It should be null instead:

    business_incorp_date: [
        null, []
      ]
    

    I’ve got it working just fine here: plnkr.co/edit/bdque81d3BO1ZcsoDhc0?p=preview.

    If it still doesn’t work for you please provide a reproduce scenario in a plunker. It is not actionable if we can’t reproduce it: https://github.com/ng-bootstrap/ng-bootstrap#you-think-youve-found-a-bug

  2. I found this while searching for the same behaviour.

    Here is a plunkr derived from examples with reactive forms http://plnkr.co/edit/vgLDwtcBymGVoMr0WDbE?p=preview

    The behaviour I was going to is, if the input is empty, then it should be valid (meaning if I manually delete the content and switch focus, it should be valid, or if ngbDatepicker clears the input, then the form element should be valid…). Can I achieve that without a button?

    One way I can think of is to listen the input for changes, and if the input is empty, then clear the calendar.

    Would you think this is clean?

  3. I found this while searching for the same behaviour.

    Here is a plunkr derived from examples with reactive forms http://plnkr.co/edit/vgLDwtcBymGVoMr0WDbE?p=preview

    The behaviour I was going to is, if the input is empty, then it should be valid (meaning if I manually delete the content and switch focus, it should be valid, or if ngbDatepicker clears the input, then the form element should be valid…). Can I achieve that without a button?

    One way I can think of is to listen the input for changes, and if the input is empty, then clear the calendar.

    Would you think this is clean?

    THANK GOD I found this, this information should be at the forefront on Angular tutorials where Bootstrap components are used with Reactive Forms