Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dropdown Component Not Initializing correctly on Navigation with Angular RouterLink #861

Open
ayoubkhial opened this issue Apr 18, 2024 · 0 comments

Comments

@ayoubkhial
Copy link

Describe the bug
When navigating between pages using Angular's routerLink, the dropdown components powered by Flowbite do not initialize correctly on the new page unless a full browser reload is performed. This issue affects navigation from a login page to an admin page, both of which utilize Flowbite's dropdown component.

To Reproduce

  1. Start the Angular application with Flowbite dropdown components on the login and admin pages.
  2. Navigate from the login page to the admin page using routerLink.
  3. Observe that the dropdown on the admin page does not function.
    Reload the browser on the admin page; the dropdown now works as expected.

Expected behavior
The dropdown components should initialize and function correctly after navigation between pages without requiring a browser reload.

Desktop (please complete the following information):

  • OS: MacOS
  • Browser: Google Chrome
  • Version: 123.0.6312.122

Additional context
Currently, I am initializing Flowbite on every NavigationEnd event by subscribing to router events in the ngOnInit lifecycle hook of the app.component.ts.

ngOnInit() {
  this.router.events.subscribe((event) => {
    if (event instanceof NavigationEnd) {
      initFlowbite();
    }
  });
}

Alternatively, a directive is used specifically on components where Flowbite is utilized to manage the initialization, ensuring that elements are properly recognized and initialized by Flowbite post-navigation. (source)

import { initFlowbite } from 'flowbite';
import { Subject, concatMap, delay, of } from 'rxjs';

const flowbiteQueue = new Subject<() => void>();

flowbiteQueue.pipe(concatMap((item) => of(item).pipe(delay(100)))).subscribe((x) => {
  x();
});

export function Flowbite() {
  return function (target: any) {
    const originalOnInit = target.prototype.ngOnInit;
    target.prototype.ngOnInit = function () {
      if (originalOnInit) {
        originalOnInit.apply(this);
      }
      initFlowbiteFix();
    };
  };
}

export function initFlowbiteFix() {
  flowbiteQueue.next(() => {
    const elements = Array.from(document.querySelectorAll('*'));
    const flowbiteElements: Element[] = [];
    const initializedElements = Array.from(document.querySelectorAll('[flowbite-initialized]'));

    for (const element of elements) {
      const attributes = Array.from(element.attributes);

      for (const attribute of attributes) {
        if (attribute.name.startsWith('data-') && !initializedElements.includes(element)) {
          flowbiteElements.push(element);
          break;
        }
      }
    }

    for (const element of flowbiteElements) {
      element.setAttribute('flowbite-initialized', '');
    }
    initFlowbite();

    for (const element of flowbiteElements) {
      const attributes: { name: string; value: string }[] = Array.from(element.attributes);
      const dataAttributes = attributes.filter((attribute) => attribute.name.startsWith('data-'));

      for (const attribute of dataAttributes) {
        element.setAttribute(attribute.name.replace('data-', 'fb-'), attribute.value);
        element.removeAttribute(attribute.name);
      }
    }
  });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant