i'm trying to create an Angular 4 custom form control as my date picker. I'm using ngx-bootstrap and i have so far setup this custom form control using an input, datepicker and popover component from ngx-bootstrap. The custom control opens a popover with the datepicker on focus, however, i need to be able to change date by interacting with the popover contents and it should close when iam not interacting with the popover or the input. I have tried to follow the hack on the ngx-bootstrap github issue. However it isn't working for my case. Any help would be appreciated.
date-picker.component.html
<input type="text" [value]="getDate() | date:'fullDate'" #popover="bs-popover" [placeholder]="placeholder" class="form-control" triggers="" (focus)="popover.show()" [popover]="popTemplate" container="body" required>
<template #popTemplate>
<datepicker [(ngModel)]="dt" [minDate]="minDate" [showWeeks]="true"
[dateDisabled]="dateDisabled"></datepicker>
</template>
date-picker.component.ts
@Component({
selector: 'app-date-picker',
templateUrl: './date-picker.component.html',
styleUrls: ['./date-picker.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DatePickerComponent),
multi: true
}
]
})
export class DatePickerComponent implements OnInit, ControlValueAccessor {
@ViewChild('popover') popover;
isOpen = false;
@Input('placeholder') placeholder;
constructor(private _er: ElementRef) {
}
@HostListener('click', ['$event']) onClick(event): void {
console.log(event);
if (
this.isOpen
&& !this._er.nativeElement.contains(event.target)
&& !this.popover._popover!._componentRef!.location.nativeElement!.contains(event.target)
) {
this.hide();
}
}
hide() {
this.isOpen = false;
this.popover.hide();
}
show() {
this.isOpen = true;
this.popover.show();
}
}
This stays open even when i click outside the input or the popover. When is used the blur event, i couldn't even interact with the calendar. It would close even before i could select date.
The @HostListener
decorator doesn't have a description in Angular API Doc, but it binds an event listener to the component host element. In your case <app-date-picker>
.
But you want to hide the popover when you click anywhere outside of the popover itself, so you need to bind the listener to the whole page (document). To do it, you must add the document:
prefix to the event name:
@HostListener('document:click', ['$event'])
I don't know if there are some other supported prefixes, maybe window
. You can play with the events using a Plunker (from this question). There is also a question about the meaning of the HostListener decorator.