2

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;
}
}
}
6
  • Do you see any error on the console? Commented Nov 3, 2016 at 17:00
  • @ClaudioRedi sorry, yes Uncaught Error: Bootstrap tooltips require Tether (tether.io) at maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/js/… at maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/js/… at maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/js/… Commented Nov 3, 2016 at 17:02
  • I'm not familiar with that error but you have an starting point for looking, it seems that something is missed to make tooltips happy Commented Nov 3, 2016 at 17:07
  • @ClaudioRedi I was able to add the script tag in my index.html to get rid of that error. Still getting the same problem with the input and datepicker though Commented Nov 3, 2016 at 17:13
  • @ClaudioRedi I changed [(ngModel)]="dt" to [ngModel]="dt" and added (ngModelChange)="getStartDate($event)" and the input still won't populate, but clicking the button that opens the datepicker again will now close it like I want it to Commented Nov 3, 2016 at 17:20

1 Answer 1

4

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:

import {DatePipe} from "@angular/common";

@Component({providers: [DatePipe]})

public constructor(fb: FormBuilder, private datePipe: DatePipe)
public dt: NgbDateStruct;
<...>
public getStartDate():number {
let timestamp = this.dt != null ? new Date(this.dt.year, this.dt.month-1, this.dt.day).getTime() : new Date().getTime();
this.secondForm.controls['startDate'].setValue(this.datePipe.transform(timestamp, 'fullDate'));
}

The markup changes to: <input style="width:250px" [value]="getStartDate()" class="form-control" type="text" [formControl]="secondForm.controls['startDate']">

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.

Also, the way it's written with the default value being new Date().getTime() means that you never have a blank value which may/may not be desired. And it's always dirty and valid.

Sign up to request clarification or add additional context in comments.

3 Comments

The input from the datepicker shows up now but getting console error Type 'number | Date' is not assignable to type 'number'. Type 'Date' is not assignable to type 'number'. Also, now my form validation does not recognize that there is input when I choose a date, so my button stays disabled unless I manually type something there. Just like in the plunker example.
Updated to so the form control is properly catching the value being set.
How can I initialize startDate and endDate to something else, or nothing? I tried 'startDate' : [null, Validators.required] but DatePipe gets in the way of that. Also, using DatePipe doesn't allow me to bank the input blank if I want, it always stays populated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.