infor-design / enterprise-wc

Enterprise-grade web component library for the Infor Design System
Apache License 2.0
27 stars 26 forks source link

IdsModuleNav: Rendering problems for dynamic content #2517

Closed anhallbe closed 2 months ago

anhallbe commented 3 months ago

Describe the bug There are a couple of issues with the IdsModuleNav related to dynamic content:

  1. If the panel is initially expanded, and menu items are added later, then they do not render at all.
  2. If the panel is expanded after the "dynamic" menu items have been added, they are visible but the selection state does not work. Also the accordion chevrons are not visible.

This is currently stopping us from using the ModuleNav, as the menu items are either dynamically loaded at runtime (based on a HTTP request), or dynamically rendered using Angular conditional syntax (@if, *ngIf @for etc). Both of these cause the issue.

Update: Similar issues with IdsAppMenu. See https://github.com/infor-design/enterprise-wc/issues/2517#issuecomment-2208710352

To Reproduce

Steps to reproduce the behavior:

  1. Clone the repository: https://github.com/anhallbe/repro-ids-module-nav
  2. Run npm install
  3. Run ng serve and open in the browser, or start the VSCode debugger.
  4. See rendering issues in module nav

Expected behavior It should be possible to add menu items after the Module Nav has been created.

Version

Screenshots

https://github.com/infor-design/enterprise-wc/assets/4991954/b2325b20-a58e-47ac-84e2-f0fb82cb30bb

Platform

Additional context Code to reproduce:

app.component.html:

<ids-container role="main">
  <ids-module-nav #moduleNav responsive>
    <ids-module-nav-bar>
      <ids-accordion>
        <ids-accordion-section slot="" grow>
          @for (action of actions; track action) {
          <ids-accordion-panel>
            <ids-module-nav-item slot="header" [icon]="action.icon">
              <ids-text font-size="16" overflow="ellipsis">{{ action.text }}</ids-text>
            </ids-module-nav-item>
            @for (child of action.children; track child) {
            <ids-accordion-panel slot="content">
              <ids-module-nav-item slot="header">
                <ids-text font-size="14">{{ child }}</ids-text>
              </ids-module-nav-item>
            </ids-accordion-panel>
            }
          </ids-accordion-panel>
          }
        </ids-accordion-section>
      </ids-accordion>
    </ids-module-nav-bar>

    <ids-module-nav-content>
      <ids-header>
        <ids-toolbar>
          <ids-toolbar-section type="button">
            <ids-button icon="menu" (click)="toggleMenu()">
            </ids-button>
          </ids-toolbar-section>
          <ids-toolbar-section type="title">
            <ids-text font-size="20" type="h1">
              Page Title
            </ids-text>
          </ids-toolbar-section>
        </ids-toolbar>
      </ids-header>

      <ids-text>
        When actions (ids-accordion-panel) are added after the Module Nav has already been created, the menu titles are
        not visible at all. When the menu is collapsed and then expanded again, the menu titles are visible but do not
        render properly. They get a different text color and the selection state and accordion chevron do not work.
      </ids-text>

    </ids-module-nav-content>
  </ids-module-nav>
</ids-container>

app.component.ts:

import { CUSTOM_ELEMENTS_SCHEMA, Component, ElementRef, viewChild } from '@angular/core';
import type IdsModuleNav from 'ids-enterprise-wc/components/ids-module-nav/ids-module-nav';

@Component({
  selector: 'app-root',
  standalone: true,
  templateUrl: './app.component.html',
  styleUrl: './app.component.css',
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppComponent {
  moduleNav = viewChild<ElementRef<IdsModuleNav>>('moduleNav');

  actions: Action[] = INITIAL_ACTIONS;

  ngAfterViewInit() {
    this.moduleNav()!.nativeElement.displayMode = "expanded";

    setTimeout(() => {
      this.actions = [...this.actions, ...DELAYED_ACTIONS];
    }, 1000)
  }

  toggleMenu() {
    const moduleNav = this.moduleNav()!.nativeElement;
    const displayMode = moduleNav.displayMode;
    moduleNav.displayMode = displayMode === "expanded" ? "collapsed" : "expanded";
  }
}

const INITIAL_ACTIONS: Action[] = [
  {
    text: "Home",
    icon: "home",
  },
  {
    text: "Warehouse",
    icon: "warehouse",
    children: [
      "Warehouse 1",
      "Warehouse 2",
      "Warehouse 3",
    ],
  },
  {
    text: "Shirts",
    icon: "shirt",
    children: [
      "Shirt 1",
      "Shirt 2",
      "Shirt 3",
    ],
  },
  {
    text: "Trucks",
    icon: "truck",
    children: [
      "Truck 1",
      "Truck 2",
      "Truck 3",
    ],
  }
];

const DELAYED_ACTIONS: Action[] = [
  {
    text: "Delayed",
    icon: "clock",
    children: [
      "Delayed 1",
      "Delayed 2",
      "Delayed 3",
    ],
  },
];

type Action = {
  text: string;
  icon: string;
  children?: string[];
}
anhallbe commented 3 months ago

Update: I can see similar issues with IdsAppMenu, so maybe the root cause is in the Accordion or some other shared component? Can be reproduced in the same repo, but on the "app-menu" branch.

https://github.com/anhallbe/repro-ids-module-nav/blob/app-menu/src/app/app.component.html

https://github.com/infor-design/enterprise-wc/assets/4991954/31a4b185-9508-4c8d-840f-77acbe3c10cf