Ngx-bootstrap: feat(popover): click outside feature

Created on 11 Jan 2017  路  17Comments  路  Source: valor-software/ngx-bootstrap

Hello, just updated to 1.1.17, everything is working amazingly, good work :) But this is not about that. Because of ng2-bootstrap now has popover support, I removed ng2-popover package as it seemed pointless to use that one anymore. The thing is, it has nice feature - popoverCloseOnClickOutside. It does what the name suggests - closes popover when clicked outside of it if set to true. Can we have this in ng2-bootstrap/popover?

comp(popover)

Most helpful comment

I will need to add this functionality...

All 17 comments

thanks ;)
you can configure popover triggers as triggers="click:blur" or other focus lost event
http://valor-software.com/ng2-bootstrap/#/popover#triggers-custom

and you can configure it globally

Thanks, will try it later today. Maybe there should be a place where all triggers could be listed and described(kinda)?

Also, in that example is used mouseenter:mouseleave, how should I use triggers to achieve this kind of flow: mouseover button shows popover, disappears when leaves button, but doesn't disappear when mouse moves from button to popover? Basicly, lets me interact with popover?

But I got your idea

@valorkin Hmm, they are not working.
click:blur disappears when I click outside of popover(correct), disappears when I click on popover(incorrect)
mouseover:blur allows to mouseover the popover(correct), but doesn't disappear when I move it out of popover(incorrect)

I will need to add this functionality...

Looking forward to it. Also it would be wise to add delay attribute to basicly delay the popover showing up and disappearing.

Hopefully, fix will be available soon (thanks @DanielKucal ), but as of now, possible hack (updated to angular4 api):

@Component({
    ...
    host: {
//`document:click` doesn't work anymore for month- and year-picker, as contents are hidden before this handler is executed. With `mousedown` click detection works properly
        "(document:mousedown)": "onClick($event)"
    },
    template:`
<div class="form-group">
    <div 
        class="input-group"

        [popover]="bodyTemplate"
        #popover="bs-popover"
        (click)="popover.show()"
    >
        <input class="form-control">
        <span class="input-group-addon">addon</span>
    </div>
</div>
<template #bodyTemplate>
    TemplateBody
</template>
`
    ...
})
export class MyComponent{
    //Do not specify there type 'PopoverDirective', but use 'any'. In this case you can use private '_popover' property (hack) as compiler cannot check access level in this case.
    @ViewChild('popover') popover;

    isOpen: boolean = false;

    constructor(private _self: ElementRef){
    }

    private onClick(event): void{
        if(
            this.closeOnBlur 
            && this.isOpen 
            && !this._self.nativeElement.contains(event.target) 
            && (
                !this.popover._popover
                || !this.popover._popover._componentRef
                || !this.popover._popover._componentRef.location
                || !this.popover._popover._componentRef.location.nativeElement
//for angular2 it should be `this.popover._popover._componentRef._nativeElement.contains()`
                || !this.popover._popover._componentRef.location.nativeElement.contains(event.target)
            )
        ){
            this.hide();
        }
    }

    hide(){
        this.isOpen = false;
        this.popover.hide();
    }

    show(){
        this.isOpen = true;
        this.popover.show();
    }

}

Does not help. What am I doing wrong?

<a [popover]="advSrcTemplate" popoverTitle="Advanced Search" placement="bottom"  #popover="bs-popover" (click)="popover.show()">Advanced Search</a>


<template #advSrcTemplate >....
</template>

import { Component, ViewChild, ElementRef } from '@angular/core';

@Component({

host: {
    "(document:click)": "onDocClick($event)"
}

})

export class ListcaregiverComponent {
@ViewChild('popover') popover:any;
public isOpen: boolean = false;

public constructor(     
    private _self: ElementRef) { }

public onDocClick(event:any):void{
if(

        this.isOpen 
        && !this._self.nativeElement.contains(event.target) 
        && !this.popover._popover!._componentRef!._nativeElement!.contains(event.target)
    ){
        this.hide();
    }
}

public hide(){
    this.isOpen = false;
    this.popover.hide();
}
 public show(){
    this.isOpen = true;
    this.popover.show();
}

}

@DanielKucal is it looking like this will get merged soon?

@PTC-JoshuaMatthews it depends on this repository maintainers, there is no feedback from them.
If you need this feature now, you can use [email protected] instead until it'll be merged here.

It is long discussion, and it continues in several repositories. I have an idea, I will build prof of concept for it, show it to you and then we will see how it will go, Ok?

@DanielKucal Thanks! Your version works great, will use that for the time being!

any updates on this? @valorkin @DanielKucal just realized that with the new version, the hack in this thread was no longer working for me lol

note that the new fix is:

    if (
      this.isOpen
      && !this._self.nativeElement.contains(event.target)
      && !this.popover._popover!._componentRef!.location.nativeElement!.contains(event.target)
    ) {
      this.hidePopover();
    }

+1, interested in this feature as well and latest build does not support it out of the box.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ghiscoding picture ghiscoding  路  3Comments

MrBlaise picture MrBlaise  路  3Comments

phmello picture phmello  路  3Comments

pgeyman picture pgeyman  路  3Comments

RolfVeinoeSorensen picture RolfVeinoeSorensen  路  3Comments