What i try to achieve is to extend ngbPopover directive and wrap in custom directive all this proeprties so instead of showing them just to include my directive.
For exa
Instead of creating a directive, you could also create a component with the selector my-popover.
This component will hold your HTML template code:
<button
type="button"
class="btn btn-primary mb-4"
placement="right-top"
[ngbPopover]="popOver"
popoverClass="popover-custom"
#popOverRef="ngbPopover"
triggers="manual"
[autoClose]="false"
(click)="popOverRef.toggle()"
(hidden)="onPopoverClose(options)"
>
Standard Picker
</button>
<ng-template #popOver>
<popover [data]="options" [popover]="popOverRef"><popover>
</ng-template>
And then finally to use that, you could do the following:
<my-popover></my-popover>
If you need to interact with that component, e.g. to listen to the click events have a look at input and output bidings of components.
Hope this helps!
For more information on the difference between components and directives, you could check this question.
Ok finally got this to work not sure why my previous code was not working. Anyway i succeed with extending ngbPopover directive. In my case i wanted popoup to be open on parent click for example button, this can be change to hover (mouseenter).... etc..
import {
ElementRef,
Directive,
Input,
TemplateRef,
EventEmitter,
Renderer2,
Injector,
ComponentFactoryResolver,
ViewContainerRef,
NgZone,
OnInit,
OnDestroy,
Inject,
ChangeDetectorRef,
ApplicationRef,
} from '@angular/core';
import { NgbPopover, NgbPopoverConfig } from '@ng-bootstrap/ng-bootstrap';
import { DOCUMENT } from '@angular/common';
@Directive({
selector: '[customPopover]',
exportAs: 'customPopover',
})
export class PopoverDirective extends NgbPopover implements OnInit {
@Input() customPopover: TemplateRef<any>;
constructor(
private _elRef: ElementRef,
private _render: Renderer2,
injector: Injector,
componentFactoryResolver: ComponentFactoryResolver,
private viewContainerRef: ViewContainerRef,
config: NgbPopoverConfig,
ngZone: NgZone,
private changeRef: ChangeDetectorRef,
@Inject(DOCUMENT) _document: any,
applicationRef: ApplicationRef
) {
super(
_elRef,
_render,
injector,
componentFactoryResolver,
viewContainerRef,
config,
ngZone,
_document,
changeRef,
applicationRef
);
this.triggers = 'manual';
this.popoverTitle = '';
this.container = 'body';
this.popoverClass = 'popover-custom';
this.autoClose = false;
}
ngOnInit(): void {
super.ngOnInit();
this.ngbPopover = this.customPopover;
// we need to listen on parent element click envet for example button
// and toggle popover
this._render.listen(this._elRef.nativeElement.parentNode, 'click', () => {
this.toggle();
});
}
ngOnDestroy(): void {
super.ngOnDestroy();
}
}
component that use this directive:
<ng-template #popTemplate>
<custom-content-comp [data]="test" [popover]="popOverRef"></custom-content-comp>
</ng-template>
<span [customPopover]="popTemplate" #popOverRef="customPopover" placement="right-top" triggers="manual">
<ng-content></ng-content>
</span>
For popTemplate i am using again custom component this can be whatever we want either string either custom template.
Usage:
<div class="col-3">
<br />
<button
type="button"
class="btn btn-primary mb-4"
customPopoverComp
>
Standard Picker
</button>
</div>