Ng-bootstrap: Popover output 'shown' emitted before rendered

Created on 23 Oct 2017  路  3Comments  路  Source: ng-bootstrap/ng-bootstrap

Bug description:

When calling a function for focusing an input inside a popover template on the output 'shown' i realized that without a timeout the input would not be selected.

My guess is that the popover event shown is emitted before template is actually rendered.

Link to minimally-working plunker that reproduces the issue:

http://plnkr.co/edit/fr0nI1GiRT22UWXaNZwJ?p=preview

Version of Angular, ng-bootstrap, and Bootstrap:

Angular:
4.0.3
ng-bootstrap:
1.0.0-beta.5
Bootstrap:
4.0.0-beta

popover bug

All 3 comments

Hi,
This issue is with the shown emitter of popover.ts which emits before the FocusDirective is totally initialized, which means emit is fired from popover before ngOnInit of FocusDirective is called. (May be someone can explain in detail the internal working of Angular Lifecycle)

There are two possible solutions:

  1. simply make emitter to be asynchronus
  2. emit on ngZone stable

I am opening a PR with second solution, which i personally prefer, as asynchronus emitter wraps the emission in setTimeout which seems tobe an overhead.

PS: the issue is also present with tooltip, and PR contains fix for both.

The root cause here is that we are not running change detection on the inserted content. It means that popover's content will be only change-detected at the end of the current zone turn, after we emit the shown event. So if we want to "fix" this we would need to manually call detect changes on the content to be inserted.

@DanielTibbing regardless of the issue on ng-bootstrap side, this is _not_ how I would approach focus setting - you should rather have a directive that you would put on an <input> you would like to focus.

@pkozlowski-opensource
Well, I am using a directive that I put on the input element. I was just trying to trigger the focus directive on the (open) event.

I solved this in my solution now by instead of using the (open) event doing a check in the ngAfterViewChecked. Since this is fired all the time I make sure to only do it once by checking a start variable that is only set to true on the (click) event.

It is a very ugly work-around, so if someone has a better suggestion I'd gladly take it :)

Here is the plunker with the workaround:
http://plnkr.co/edit/CAUAAjMT7hNfj8pSj7Ly?p=preview

Was this page helpful?
0 / 5 - 0 ratings

Related issues

raysunqi picture raysunqi  路  3Comments

Palacios95 picture Palacios95  路  3Comments

GuitarHero1969 picture GuitarHero1969  路  3Comments

CarlosTorrecillas picture CarlosTorrecillas  路  3Comments

rolandoldengarm picture rolandoldengarm  路  3Comments