2

I am using ng2-bootstrap datepicker in my angular2 application. And I want to hide the datepicker popup on clicking outside. I tried the solution suggested in this question.

But it doesn't work right, when choosing a date or switching to the months/year dialog, it closes the datepicker.

After investigation I discovered that the cause of this problem is that event target returned on click was not in the element ref initially but it is obtained on click with ngIf in the datepickers component implementation.

Here is a plunker addressing the issue.

Any suggestions how to solve this ?.

Community
  • 1
  • 1
Salma Hamed
  • 2,000
  • 4
  • 26
  • 45

3 Answers3

3

You need to change the click event to mousedown.

import {Component, Input, Output, ElementRef} from '@angular/core';

@Component({
    selector: 'my-datepicker',
    host: {
        '(document:mousedown)': 'onClick($event)',
    },
    template: `
      <label>{{label}}</label>
      <input [(ngModel)]="dateModel" class="form-control" (focus)="showPopup()" />
      <datepicker class="popup" *ngIf="showDatepicker" [(ngModel)]="dateModel" [showWeeks]="true"></datepicker>
  `,
    styles: [`
    .popup {
      position: absolute;
      background-color: #fff;
      border-radius: 3px;
      border: 1px solid #ddd;
      height: 251px;
    }
  `],
})
export class DatepickerComponent {
    @Input() dateModel: Date;
    private showDatepicker: boolean = false;

    constructor(private _eref: ElementRef) { }

    showPopup() {
        this.showDatepicker = true;
    }

    onClick(event) {
       if (!this._eref.nativeElement.contains(event.target)) {
           this.showDatepicker = false;
       }
    }
}

Check out this plunker

AMagyar
  • 5,108
  • 3
  • 13
  • 17
0

You could attach a listener to the click event on the window. This will capture all clicks.

To prevent the datepicker from being closed on a click on it, you can add a listener to the datepicker (or any element that should not close the datepicker) and call stopPropagation on the MouseEvent.

constructor(private el: ElementRef) {
    this.el.nativeElement.onclick = (ev: MouseEvent) => {
        ev.stopPropagation(); //Do not close Datepicker
    };
    window.addEventListener("click", this.handleClick);
}

handleClick = (ev: MouseEvent) => {
    this.showDatepicker = false;
};

ngOnDestroy() { //Do not forget to remove the listener
    window.removeEventListener("click", this.handleClick);
}
Drast
  • 45
  • 2
  • 9
0

Here is very quick and simple solution I have done,

in your html file

<div class="input-group">
      <input class="form-control" placeholder="yyyy-mm-dd"
             name="dp" [(ngModel)]="model" ngbDatepicker [dayTemplate]="customDay" [markDisabled]="isDisabled" #datepicker="ngbDatepicker">
      <button class="input-group-addon" (click)="d.toggle()" type="button">
        <img src="img/calendar-icon.svg" style="width: 1.2rem; height: 1rem; cursor: pointer;"/>
      </button>
    </div>

in your component.ts file

// local reference varible of datepicker input
@Viewchild('datepicker') datepicker;

// listen to document click event and handle closeDponOutsideClick event
@HostListener('document:click', ['$event'])
closeDponOutsideClick(event) {
if (event.target.offsetParent !== null && event.target.offsetParent.tagName !== 'NGB-DATEPICKER') {
this.datepicker.close();
  }
}

Description: listen to the document click event and check that targeted offset parent element is not null and as well as its tag name is not equals to 'NGB-DATEPICKER' because outside click of datepicker you always get different offsetParent name than 'NGB-DATEPICKER' .

Hope this helps someone.

Montu Patel
  • 115
  • 1
  • 1
  • 7