Primeng: Display issue with accordion nested inside overlay

Created on 14 Aug 2018  ·  14Comments  ·  Source: primefaces/primeng

I'm submitting a ... (check one with "x")

[X] bug report => Search github for a similar issue or PR before submitting
[ ] feature request => Please check if request is not on the roadmap already https://github.com/primefaces/primeng/wiki/Roadmap
[ ] support request => Please do not submit support request here, instead see http://forum.primefaces.org/viewforum.php?f=35

Current behavior
In some cases, accordion controls (placed on overlay panels) will be "closed" but will still be displaying their content.

Expected behavior
A closed accordion should not display its content.

Minimal reproduction of the problem with instructions
https://github-xwovh7.stackblitz.io/

  1. Click on the button to display the overlay panel.
  2. Do not change any accordion state. Just click outside of the overlay to dismiss it.
  3. Click on the button a second time. The overlay displays with the accordion in a bad state. The individual accordion headers still show in a closed state (i.e. rendered with the closed color & the chevron is pointed left), but the accordion content is displaying.
  • Angular version: 6.1.2
  • PrimeNG version: 6.1
  • Browser: Chrome 68
LTS-FIXED-7.1.5 defect

Most helpful comment

I have encounter this error when using p-accordion inside a p-dialog. First time i open dialog, it works fine, but if i close the dialog and reopen, all accordions are opened but without being selected:

  • Angular version: 7.1.3
  • PrimeNG version: 6.1.2
  • Browser: Chrome 71
<p-dialog [(visible)]="ayudaContenedores"
          [draggable]="false"
          [resizable]="false"
          [modal]="true"
          [blockScroll]="true"
          [closeOnEscape]="true"
          [responsive]="true"
          [style]="{'max-width': '1280px'}">
    <p-header>
        Instrucciones para importar contenedores
    </p-header>
    <p-accordion [multiple]="true">
        <p-accordionTab header="{{ 'Campo Contenedor'|trans }}" selected="false">
            <div [innerHTML]="'Explicación Contenedor'|trans"></div>
        </p-accordionTab>
        <p-accordionTab header="{{ 'Campo Id'|trans }}">
            <div [innerHTML]="'Explicación Id'|trans"></div>
        </p-accordionTab>
        <p-accordionTab header="{{ 'Campo Nombre'|trans }}">
            <div [innerHTML]="'Explicación Nombre'|trans"></div>
        </p-accordionTab>
        <p-accordionTab header="{{ 'Campo Codigo'|trans }}">
            <div [innerHTML]="'Explicación Codigo'|trans"></div>
        </p-accordionTab>
    </p-accordion>
</p-dialog>

All 14 comments

One addition to this report: It appears this also affects nested panels and fieldsets - seemingly anything that uses a collapsible paradigm.

This one might be related:

When an Overlay Panel contains an inline ColorPicker, the ColorPicker disappears when clicking outside the Overlay Panel (it's actually visible to the naked eye that the dom of the ColorPicker gets removed before the Overlay Panel disappears). Showing the Overlay Panel a second time only renders the bare skeleton of the ColorPicker. I guess that ColorPicker itself contains an Overlay Panel and that this nesting is not correctly handled. Maybe this is also happening in the other use cases mentioned in this ticket.

EDIT: the same behaviour when adding an inline ColorPicker to a Dialog.

I'm more and more convinced that all these issues are related. The problem seems to be related to the animations. When the animation to hide the Overlay runs, the animation to hide the Color Picker also runs. It creates a nice effect so I'm in favor of keeping it.
But when the Overlay is displayed again, the animation of the Color Picker doesn't run anymore and so it is only partially rendered. I think that the same happens with other components that have animations like the Accordion.

I could easily see this behavior by setting breakpoints on the onOverlayAnimationStart methods of the different components involved.

Stumbled across this open issue on Angular:

https://github.com/angular/angular/issues/20823

Apparently when nesting animations the child animation does not trigger automatically. You need to trigger it from inside the parent animation. In the case of the calendar it means that the opacity remains '0' and so the calendar is not visible the second time.

I'm pretty sure now that the issues mentioned by Kirk and the one I noticed are related.

Aha! I think I found the solution. The problem seems to be the names of the states. Both OverlayPanel as ColorPicker are using 'void' and 'visible' as animation state names. By means of a test I modified the ones of ColorPicker to 'void2' and 'visible2' and now everything works fine in both inline as popup mode.

I've seen that Accordion also uses the name 'visible' but does not use 'void' (it uses 'hidden'). I think that's the reason why part of the Accordion becomes visible when the overlay becomes visible.

So I guess that all animation states should be reviewed and made unique. (How to do this for nested components of the same type might be a challenge)

Shouldn't this be fixed on the Angular side? It sounds like a bug of Angular.

It could indeed be a bug in Angular already introduced in Version 5.

https://github.com/angular/angular/issues/20811

Thanks for all the investigative work @DavyDeDurpel .
It does sound like an Angular bug, but at the same time, it's pretty significant to tell all Primeng users "don't nest animated components", so if there are mitigations that can be accomplished here, that would be my vote.

I agree because I don't think that this issue will be fixed any time soon in Angular. I think that it's an undocumented behaviour of the Animations library. I've read in the documentation that the whole idea of their Animation library is to allow for complex nested animations. The problem seems to be that nobody actual succeeds in doing so :-)

I have encounter this error when using p-accordion inside a p-dialog. First time i open dialog, it works fine, but if i close the dialog and reopen, all accordions are opened but without being selected:

  • Angular version: 7.1.3
  • PrimeNG version: 6.1.2
  • Browser: Chrome 71
<p-dialog [(visible)]="ayudaContenedores"
          [draggable]="false"
          [resizable]="false"
          [modal]="true"
          [blockScroll]="true"
          [closeOnEscape]="true"
          [responsive]="true"
          [style]="{'max-width': '1280px'}">
    <p-header>
        Instrucciones para importar contenedores
    </p-header>
    <p-accordion [multiple]="true">
        <p-accordionTab header="{{ 'Campo Contenedor'|trans }}" selected="false">
            <div [innerHTML]="'Explicación Contenedor'|trans"></div>
        </p-accordionTab>
        <p-accordionTab header="{{ 'Campo Id'|trans }}">
            <div [innerHTML]="'Explicación Id'|trans"></div>
        </p-accordionTab>
        <p-accordionTab header="{{ 'Campo Nombre'|trans }}">
            <div [innerHTML]="'Explicación Nombre'|trans"></div>
        </p-accordionTab>
        <p-accordionTab header="{{ 'Campo Codigo'|trans }}">
            <div [innerHTML]="'Explicación Codigo'|trans"></div>
        </p-accordionTab>
    </p-accordion>
</p-dialog>

faced the same issue (accordion inside p-dialog)

Any workarround so far to be able to use accordions inside p-dialogs?

I'm not sure whether this is applicable to the issues reported in this thread or not, but we're working around display defects with collapsible components nested inside dialogs by binding to the onAfterToggle event of the nested component (in our case p-fieldset) a method that maximizes then restores the dialog:

…
    @ViewChild(Dialog) private dialogViewChild: Dialog;
…
    /** Work-around for dialog footer getting cut-off and dialog becoming "stuck" */
    public onAfterToggle(): void {
        if (!this.dialogViewChild.maximized) {
            this.dialogViewChild.maximize();
            this.dialogViewChild.revertMaximize();
        }
    }
…

It results in a "jumpy" dialog, so is not ideal, but the hack maintains UI usability.

I was able to get basic functionality for the accordion in the overlay by including the following css in my component css file. Not a perfect solution and also not as smooth as it should be. Would be great if we can get a permanent working solution. It sets the height of the content of the tab to zero when aria-hidden is true.

:host ::ng-deep div[aria-hidden="true"].ui-accordion-content-wrapper {
    height: 0px;
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

KannanMuruganmony picture KannanMuruganmony  ·  3Comments

jisqaqov picture jisqaqov  ·  3Comments

gatapia picture gatapia  ·  3Comments

Faigjaz picture Faigjaz  ·  3Comments

garethlewis picture garethlewis  ·  3Comments