Reputation: 100
I want to create a component in angular with custom directive that toggle (show/hide) another component. My directive is [appDatepicker] and i want to put this directive to any input and then automatically show datepicker component when use click on the input. So I created a directive, component and medule that can export like below.
datepicker.directive.ts
import { Directive, ElementRef, HostListener, Inject } from '@angular/core';
import { DatepickerComponent } from './datepicker.component';
@Directive({
selector: '[appDatepicker]',
})
export class DatepickerDirective {
constructor(private el: DatepickerComponent) {}
@HostListener('click', ['$event.target']) onClick(btn) {
this.el.togglePicker();
}
}
datepicker.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'datepicker',
templateUrl: 'datepicker.component.html',
styleUrls: ['datepicker.component.scss']
})
export class DatepickerComponent implements OnInit {
isPickerOpen:boolean=false;
constructor() { }
ngOnInit() { }
public togglePicker(){
this.isPickerOpen = !this.isPickerOpen;
}
}
datepicker.component.html
<div class="datepicker-container">
<ng-content></ng-content>
<div class="datepicker" ></div>
<div class="date-picker-date" *ngIf="isPickerOpen">
this is the datepicker popup
</div>
</div>
datepicker.module.ts
import { NgModule } from '@angular/core';
import { DatepickerComponent } from './datepicker.component';
import { DatepickerDirective } from './datepicker.directive';
@NgModule({
declarations: [DatepickerDirective],
imports: [],
exports: [],
providers: [],
})
export class DatepickerModule {}
And I use the directive in main app like this
app.component.html
<input appDatepicker class="datepicker-input"/>
But the issue is directive doesn't call the this.el.togglePicker() method. el returns the ElementRef. But Seems it does not access the datepicker component methods. Can anyone help me how to call the method togglePicker() from the directive.
Upvotes: 2
Views: 1069
Reputation: 1373
You need to declare your component as a generic type and then reference that in the directive.
import { Directive, HostListener, Input } from '@angular/core';
import { DatepickerComponent } from './datepicker.component';
@Directive({
selector: '[appDatepicker]'
})
export class DatepickerDirective<T> {
@Input('appDatepicker') dtPicker: DatepickerComponent<T>;
constructor() {}
@HostListener('click', ['$event']) onClick(event) {
if (this.dtPicker) {
this.dtPicker.togglePicker();
event.stopPropagation();
}
}
}
and change your component
import { Component } from '@angular/core';
@Component({
selector: 'datepicker',
templateUrl: './datepicker.component.html'
})
export class DatepickerComponent<T> {
isPickerOpen: boolean = false;
constructor() {}
public togglePicker() {
console.log('togglePicker');
this.isPickerOpen = !this.isPickerOpen;
}
}
and you can use the directive as below in your components
<input [appDatepicker]="dt1" class="datepicker-input"/>
<datepicker #dt1></datepicker>
and add datepickercomponent in the declarations part of DatepickerModule
Upvotes: 1