【问题标题】:Extend ng-boostrap popover component with custom angular directive使用自定义角度指令扩展 ng-bootstrap popover 组件
【发布时间】:2020-04-03 11:04:43
【问题描述】:

我试图实现的是扩展 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 扩展为下面的代码,但我很难用这种方法显示 popover。这是可行的还是其他想法?

自定义指令:

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

【问题讨论】:

    标签: javascript angular typescript ng-bootstrap


    【解决方案1】:

    好的,终于让它工作了,不知道为什么我以前的代码不起作用。无论如何,我成功扩展了 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>
    

    【讨论】:

      【解决方案2】:

      除了创建指令之外,您还可以使用选择器 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

      希望这会有所帮助!

      有关组件和指令之间区别的更多信息,您可以查看此question

      【讨论】:

      • 嘿@gerstams 是的,起初我只是使用了包含所有这些 html 的自定义组件,它运行良好。但事情是这样的 html 是“硬编码”的,对吗?它始终是带有弹出框的按钮。这就是为什么我想要自定义指令或自定义属性组件,它们只会将这些属性“附加”到 html 元素(按钮或输入或列表项......等等......
      • 好的。有你!也许这个question helps。否则,在描述你想要做的事情时,请尽量准确一点。
      • 这是为了添加 html 作为内容而不是简单的字符串。我在上面的例子中已经有了。有人解释说我想要自定义指令来包装所有 ng bootstrap popover 属性,我可以这样称呼它: where customDirective可能会“附加”那些弹出道具。
      猜你喜欢
      • 2014-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-06
      • 2020-07-19
      相关资源
      最近更新 更多