如何扩展NgbDropdown或为其编写包装



基本上,对于所有下拉列表,我想每次打开NgbDropDown时运行myOpenFunction(),每次关闭下拉列表时运行myCloseFunction()

我想我可以写一个自定义指令来扩展NgbDropDown,并在下拉之前和之后运行一个函数。像这样的东西:

<div myCustomDropdown> <!-- using my own directive instead of ngbDropdown -->
<button  ngbDropdownToggle>Toggle dropdown</button>
<div ngbDropdownMenu>
<button ngbDropdownItem>Action - 1</button>
<button ngbDropdownItem>Another Action</button>
</div>
</div>

到目前为止,我在这里尝试了什么

@Directive({
selector: '[myCustomDropdown]'
})
export class DropdownDirective extends NgbDropdown implements OnDestroy {

constructor(_changeDetector: ChangeDetectorRef, config: NgbDropdownConfig, @Inject(DOCUMENT)  _document: any,
_ngZone: NgZone, _elementRef: ElementRef<HTMLElement>, _renderer: Renderer2,
@Optional() ngbNavbar: NgbNavbar) {
super(_changeDetector, config, _document, _ngZone, _elementRef, _renderer, ngbNavbar);
}

ngOnDestroy() {
super.ngOnDestroy();
}
}

它抛出错误

core.js:6185 ERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(TestModule)[NgbDropdown -> NgbDropdown -> NgbDropdown -> NgbDropdown]: 
NullInjectorError: No provider for NgbDropdown!

另一个方法是创建一个指令并使用HostBinding

@Directive({
selector: '[extend-dropdown]'
})
export class ExtendDropdown {
@Input('extend-dropdown')func:(boolean)=>any;
@HostListener('openChange',['$event']) openChange(event)
{
console.log('inner function',event)
this.func && this.func(event);
}
}

您用作

<div ngbDropdown [extend-dropdown]="open" class="d-inline-block">
...
</div>
//If you has a function in .ts
open(event)
{
console.log("from main",event)
}

<div ngbDropdown extend-dropdown class="d-inline-block">
...
</div>

参见堆叠式

您只需为所有配置的下拉列表创建一个包装组件,就可以将其用作ngbDropdown

下拉

<div ngbDropdown class="d-inline-block">
<button class="btn btn-outline-primary" [id]="id" 
ngbDropdownToggle>Toggle dropdown</button>
<div ngbDropdownMenu [attr.aria-labelledby]="id">
<button 
*ngFor="let item of items" 
ngbDropdownItem 
(click)="clickHandler(item.action)" >
{{item.label}}
</button>
</div>
</div>

组件

export class DropdownComponent implements OnInit {
@Input() items =[];
constructor() { }
clickHandler(action){
if (action){
action()
}
}
}

现在你有了一个ngbDropdown的可重用组件库,可以接受带有回调的qan项目列表

应用程序模板

<app-dropdown [items]="dropDownItems"></app-dropdown>

演示

@Eliseo答案的启发,到目前为止ngbDropdown指令有一个名为openChange的方法,它将告诉boolen值的开放状态库我们可以创建一个新的事件,如open和close,并发出开放状态的值库

ExtendDropdownDirective

@Directive({
selector: "[extend-dropdown]"
})
export class ExtendDropdownDirective {
@Output() open: EventEmitter<any> = new EventEmitter();
@Output() close: EventEmitter<any> = new EventEmitter();
@HostListener("openChange", ["$event"]) openChangeHandler(state: boolean) {
if (state) {
this.open.emit();
} else {
this.close.emit();
}
}
}

现在我们可以像这个一样使用它

div ngbDropdown extend-dropdown class="d-inline-block" (open)="open()" (close)="close()">
...
</div>

演示

最新更新