import { Component , OnInit , Input , OnChanges , SimpleChanges , SimpleChange , Output , EventEmitter } from '@angular/core' ; import { NgbCalendar , NgbDate , NgbDateParserFormatter , NgbDateStruct } from '@ng-bootstrap/ng-bootstrap' ; @ Component ( { selector : 'app-dual-date-picker' , templateUrl : './dual-date-picker.component.html' , styleUrls : [ './dual-date-picker.component.scss' ] } ) export class DualDatePickerComponent implements OnInit , OnChanges { @ Input ( ) minDate : Date ; @ Input ( ) maxDate : Date ; @ Input ( ) currentStartDate : Date ; @ Input ( ) currentEndDate : Date ; @ Output ( ) dateChanged = new EventEmitter < { endDate : Date ; startDate : Date ; } > ( ) ; private internalMinDate : NgbDateStruct ; private internalMaxDate : NgbDateStruct ; hoveredDate : NgbDate ; fromDate : NgbDate ; toDate : NgbDate ; constructor ( public calendar , public formatter ) { } ngOnChanges ( simple ) { this . toDate = this . dateToNgbDate ( this . currentEndDate ) ; this . fromDate = this . dateToNgbDate ( this . currentStartDate ) ; } ngOnInit ( ) { this . internalMaxDate = this . dateToNgbDate ( this . maxDate ) ; this . internalMinDate = this . dateToNgbDate ( this . minDate ) ; } dateToNgbDate ( date ) { return NgbDate . from ( { year : date . getFullYear ( ) , month : date . getMonth ( ) + 1 , day : date . getDate ( ) } ) ; } onDateSelection ( date ) { if ( ! this . fromDate && ! this . toDate ) { this . fromDate = date ; } else if ( this . fromDate && ! this . toDate && ! date . before ( this . fromDate ) ) { this . toDate = date ; } else { this . toDate = null ; this . fromDate = date ; } if ( this . fromDate && this . toDate ) { this . currentStartDate . setFullYear ( this . fromDate . year , this . fromDate . month - 1 , this . fromDate . day ) ; this . currentEndDate . setFullYear ( this . toDate . year , this . toDate . month - 1 , this . toDate . day ) ; this . dateChanged . emit ( { endDate : this . currentEndDate , startDate : this . currentStartDate } ) ; } } isHovered ( date ) { return this . fromDate && ! this . toDate && this . hoveredDate && date . after ( this . fromDate ) && date . before ( this . hoveredDate ) ; } isInside ( date ) { return date . after ( this . fromDate ) && date . before ( this . toDate ) ; } isRange ( date ) { return date . equals ( this . fromDate ) || date . equals ( this . toDate ) || this . isInside ( date ) || this . isHovered ( date ) ; } validateInput ( currentValue , input ) { const parsed = this . formatter . parse ( input ) ; return parsed && this . calendar . isValid ( NgbDate . from ( parsed ) ) ? NgbDate . from ( parsed ) : currentValue ; } isDisabled = ( date , current ) => { return date . before ( this . internalMinDate ) || date . after ( this . internalMaxDate ) ; } ; }