使用自定义 angular 指令扩展 ng-bootstrap popover 组件
Extend ng-boostrap popover component with custom angular directive
我试图实现的是扩展 ngbPopover 指令并将所有这些属性包装在自定义指令中,而不是仅仅显示它们以包含我的指令。
例如我像这样使用 ngbpopover:
<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>
我最后的目标是:
<button type="button" class="btn btn-primary mb-4" customDirective></button>
所以所有这些道具都在 customDirective 中处理。试图将 ngbPopoverDirective 扩展为下面的代码,但我很难用这种方法显示弹出窗口。这是可行的还是其他想法?
自定义指令:
import {
Directive,
ElementRef,
Renderer2,
Injector,
ComponentFactoryResolver,
ViewContainerRef,
NgZone,
Inject,
ChangeDetectorRef,
ApplicationRef,
Input,
OnInit,
} from '@angular/core';
import { NgbPopover, NgbPopoverConfig } from '@ng-bootstrap/ng-bootstrap';
import { DOCUMENT } from '@angular/common';
@Directive({
selector: '[popover]'
})
export class PopoverDirective extends NgbPopover implements OnInit {
@Input()
popover: string;
config: NgbPopoverConfig = {
autoClose: false,
placement: 'right-top',
triggers: "manual",
container: 'body',
disablePopover: false,
popoverClass: 'popover-custom',
openDelay: 0,
closeDelay: 0
}
constructor(
_elementRef: ElementRef<HTMLElement>,
_renderer: Renderer2,
injector: Injector,
componentFactoryResolver: ComponentFactoryResolver,
viewContainerRef: ViewContainerRef,
config: NgbPopoverConfig,
_ngZone: NgZone,
@Inject(DOCUMENT) _document: any,
_changeDetector: ChangeDetectorRef,
applicationRef: ApplicationRef
) {
super(
_elementRef,
_renderer,
injector,
componentFactoryResolver,
viewContainerRef,
config,
_ngZone,
_document,
_changeDetector,
applicationRef
);
console.log("here");
}
ngOnInit() {
console.log("onInit")
}
}
除了创建指令,您还可以使用选择器 my-popover.
创建组件
此组件将包含您的 HTML 模板代码:
<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>
最后要使用它,您可以执行以下操作:
<my-popover></my-popover>
如果您需要与该组件交互,例如要收听点击事件,请查看 input and output bidings of components.
希望对您有所帮助!
有关组件和指令之间差异的更多信息,您可以查看此。
好的,终于可以正常工作了,不知道为什么我以前的代码不起作用。无论如何,我成功地扩展了 ngbPopover 指令。在我的例子中,我希望弹出窗口在父点击时打开,例如按钮,这可以更改为悬停(鼠标输入)......等..
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();
}
}
使用此指令的组件:
<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>
对于 popTemplate,我再次使用自定义组件,这可以是我们想要的任何字符串或自定义模板。
用法:
<div class="col-3">
<br />
<button
type="button"
class="btn btn-primary mb-4"
customPopoverComp
>
Standard Picker
</button>
</div>
我试图实现的是扩展 ngbPopover 指令并将所有这些属性包装在自定义指令中,而不是仅仅显示它们以包含我的指令。
例如我像这样使用 ngbpopover:
<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>
我最后的目标是:
<button type="button" class="btn btn-primary mb-4" customDirective></button>
所以所有这些道具都在 customDirective 中处理。试图将 ngbPopoverDirective 扩展为下面的代码,但我很难用这种方法显示弹出窗口。这是可行的还是其他想法?
自定义指令:
import {
Directive,
ElementRef,
Renderer2,
Injector,
ComponentFactoryResolver,
ViewContainerRef,
NgZone,
Inject,
ChangeDetectorRef,
ApplicationRef,
Input,
OnInit,
} from '@angular/core';
import { NgbPopover, NgbPopoverConfig } from '@ng-bootstrap/ng-bootstrap';
import { DOCUMENT } from '@angular/common';
@Directive({
selector: '[popover]'
})
export class PopoverDirective extends NgbPopover implements OnInit {
@Input()
popover: string;
config: NgbPopoverConfig = {
autoClose: false,
placement: 'right-top',
triggers: "manual",
container: 'body',
disablePopover: false,
popoverClass: 'popover-custom',
openDelay: 0,
closeDelay: 0
}
constructor(
_elementRef: ElementRef<HTMLElement>,
_renderer: Renderer2,
injector: Injector,
componentFactoryResolver: ComponentFactoryResolver,
viewContainerRef: ViewContainerRef,
config: NgbPopoverConfig,
_ngZone: NgZone,
@Inject(DOCUMENT) _document: any,
_changeDetector: ChangeDetectorRef,
applicationRef: ApplicationRef
) {
super(
_elementRef,
_renderer,
injector,
componentFactoryResolver,
viewContainerRef,
config,
_ngZone,
_document,
_changeDetector,
applicationRef
);
console.log("here");
}
ngOnInit() {
console.log("onInit")
}
}
除了创建指令,您还可以使用选择器 my-popover.
创建组件此组件将包含您的 HTML 模板代码:
<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>
最后要使用它,您可以执行以下操作:
<my-popover></my-popover>
如果您需要与该组件交互,例如要收听点击事件,请查看 input and output bidings of components.
希望对您有所帮助!
有关组件和指令之间差异的更多信息,您可以查看此
好的,终于可以正常工作了,不知道为什么我以前的代码不起作用。无论如何,我成功地扩展了 ngbPopover 指令。在我的例子中,我希望弹出窗口在父点击时打开,例如按钮,这可以更改为悬停(鼠标输入)......等..
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();
}
}
使用此指令的组件:
<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>
对于 popTemplate,我再次使用自定义组件,这可以是我们想要的任何字符串或自定义模板。
用法:
<div class="col-3">
<br />
<button
type="button"
class="btn btn-primary mb-4"
customPopoverComp
>
Standard Picker
</button>
</div>