简体   繁体   English

使用自定义 angular 指令扩展 ng-boostrap 弹出框组件

[英]Extend ng-boostrap popover component with custom angular directive

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.我试图实现的是扩展 ngbPopover 指令并将所有这些属性包含在自定义指令中,而不是仅仅为了包含我的指令而显示它们。

For example i am using ngbpopover like this:例如,我正在使用这样的 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>

My goal at the end is to have something like:我最后的目标是拥有类似的东西:

<button type="button" class="btn btn-primary mb-4" customDirective></button>

so all this props to be handled inside customDirective.所以所有这些道具都在 customDirective 中处理。 Tried to extend ngbPopoverDirective as code below but i struggle to show popover with this approach.试图将 ngbPopoverDirective 扩展为下面的代码,但我很难用这种方法显示 popover。 Is this doable or some other idea?这是可行的还是其他想法?

Custom directive:自定义指令:

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")
    }
}

Instead of creating a directive, you could also create a component with the selector my-popover .除了创建指令之外,您还可以使用选择器my-popover创建一个组件。

This component will hold your HTML template code:该组件将保存您的 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>

And then finally to use that, you could do the following:最后要使用它,您可以执行以下操作:

<my-popover></my-popover>

If you need to interact with that component, eg to listen to the click events have a look at input and output bidings of components .如果您需要与该组件交互,例如收听点击事件,请查看组件的输入和 output 投标

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.无论如何,我成功扩展了 ngbPopover 指令。 In my case i wanted popoup to be open on parent click for example button, this can be change to hover (mouseenter).... etc..在我的情况下,我希望在父单击例如按钮时打开弹出窗口,这可以更改为 hover (mouseenter)....等等。

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.对于popTemplate,我再次使用自定义组件,这可以是我们想要的任何字符串或自定义模板。

Usage:用法:

<div class="col-3">
                <br />
                <button
                    type="button"
                    class="btn btn-primary mb-4"
                    customPopoverComp
                    >
                    Standard Picker
                    </button>
            </div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM