Drew13 Drew13 - 1 month ago 34
TypeScript Question

Value not being set on input from Angular 2 Bootstrap datepicker

I have an input which I want to populate with an Angular 2 Bootstrap datepicker. When the page opens, the value is initiated with today's date by using

value="{{ getStartDate() | date:'fullDate'}}"
. But when I click the button and open the datepicker and choose a new date, the value does not populate the input. Also I can no longer click the button again to close the datepicker.

HTML:

<form class="form-inline">
<div>
<div class="form-group" [ngClass]="{'has-error':!secondForm.controls['startDate'].valid && secondForm.controls['startDate'].touched}">
<input value="{{ getStartDate() | date:'fullDate'}}" style="width:250px" class="form-control" type="text" [formControl]="secondForm.controls['startDate']">
</div>
<div style="display:inline-block">
<ngb-datepicker *ngIf="startCheck==true;" [(ngModel)]="dt" class="dropdown-toggle" [ngModelOptions]="{standalone: true}" style="position:absolute; z-index:1"></ngb-datepicker>
</div>
<button type="button" class="btn icon-calendar" (click)="showDatePick()"></button>
<button type="button" class="btn icon-search" [disabled]="!secondForm.valid"></button>
</div>
</form>


Typescript:

import { Component } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import {NgbModule} from '@ng-bootstrap/ng-bootstrap';
import {NgbDateStruct} from '@ng-bootstrap/ng-bootstrap';

@Component({
selector: 'calendar-pick',
styleUrls: ['../app.component.css'],
templateUrl: './calendarpick.component.html'
})

export class CalendarPickComponent {
public dt:Date = new Date();
public startCheck: boolean = false;
//Might need to change this to complexForm, not sure yet
secondForm : FormGroup;

public constructor(fb: FormBuilder) {
this.secondForm = fb.group({
'startDate' : [this.dt, Validators.required]
})
this.secondForm.valueChanges.subscribe( (form: any) => {
console.log('form changed to:', form);
}
);
}

public getStartDate():number {
return this.dt && this.dt.getTime() || new Date().getTime();
}

public showDatePick():void {
if (this.startCheck == false){
this.startCheck = true;
} else {
this.startCheck = false;
}
}
}

Answer

The ng-bootstrap datepicker's model is not a Date() object it is an NgbDateStruct which consists of {month, day, year}

To get the desired behavior, then, the code looks like:

public dt: NgbDateStruct;
<...>
public getStartDate():number {
return this.dt != null ? new Date(this.dt.year, this.dt.month-1, this.dt.day) : new Date().getTime();
}

Here's the complete plunker: https://plnkr.co/edit/zqGpoJZ1psKmST0S7Ix0?p=preview

Note that the ng-bootstrap team's month index is 0 based and not one based which is maddening when using the native Date object in combination with the NgbDate.

Comments