Skip to content

Instantly share code, notes, and snippets.

@OmarMtya
Last active July 3, 2024 19:01
Show Gist options
  • Save OmarMtya/9ce68c563893d1c774f11a94ea73a31c to your computer and use it in GitHub Desktop.
Save OmarMtya/9ce68c563893d1c774f11a94ea73a31c to your computer and use it in GitHub Desktop.
Flowbite decorator to fix Angular routing problem
import { initFlowbite } from "flowbite";
import { Subject, concatMap, delay, of } from "rxjs";
let flowbiteQueue = new Subject<any>();
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 = document.querySelectorAll('*');
const flowbiteElements = [];
const initializedElements = Array.from(document.querySelectorAll('[flowbite-initialized]'));
for (let i = 0; i < elements.length; i++) {
const element = elements[i];
const attributes = element.attributes;
for (let j = 0; j < attributes.length; j++) {
const attribute = attributes[j];
if (attribute.name.startsWith('data-')) {
// add to the flowbiteElements array if it doesn't exist
if (!flowbiteElements.includes(element) && !initializedElements.find(x => x.isEqualNode(element))) {
flowbiteElements.push(element);
}
}
}
}
// add an attribute to the element to indicate that it has been initialized
for (let i = 0; i < flowbiteElements.length; i++) {
const element = flowbiteElements[i];
element.setAttribute('flowbite-initialized', '');
}
initFlowbite();
flowbiteElements.forEach(element => {
const attributes: { name: string; value: string }[] = Array.from(element.attributes);
const dataAttributes = attributes.filter(attribute => attribute.name.startsWith('data-'));
dataAttributes.forEach(attribute => {
element.setAttribute(attribute.name.replace('data-', 'fb-'), attribute.value);
element.removeAttribute(attribute.name);
});
});
});
}
@tinasche
Copy link

This is awesome and has been working well for my issues so far, thank you. Though it gave an initial error in the InitFlowbiteFix function with TypeScript, just explicitly made the flowbiteElements as any type like below and works well.

const flowbiteElements:any[] = [];

@juanpabloguerra16
Copy link

Usualmente lo que hago es crear componentes que van a recibir el ngfor directamente, por ejemplo, tienes tu contenido dinámico que recibe el ngfor, mételo todo a un componente aparte y aplica la directiva.

Lo que hace: es necesario ejecutar la función de iniciación cuando se crea un componente, pero como el ngfor es muy probable que no existan los elementos cuando se crea su padre, o es probable que los elementos dentro del ngFor cambien si el arreglo cambia, entonces los elementos que se bindearon ya no existen, aunque sea la misma información.

Por lo cual, todos los componentes que uso en un ngFor o que se van a cargar de manera dinámica por un request http, por ejemplo, los meto dentro de componentes individuales con el decorador

Debería de funcionar aunque sea la versión 17. Yo también estoy usando la versión 17 en un proyecto y utilicé el mismo decorador, aunque no estoy utilizando standalone components. Quizá están faltando los imports de flowbite? Podría ser una buena idea que compartas tu componente esqueleto y ver si puedo replicar el error en mi proyecto

Tu sugieres hacer el HTTP request adentro del componente que contiene el ngfor? O sugieres que se le pase la data al componente a traves de input data binding?

Dejame ver si puedo hacer un esqueleto con API y todo para que puedas replicarlo. Muchas gracias por tu ayuda @OmarMtya

@OmarMtya
Copy link
Author

Usualmente lo que hago es crear componentes que van a recibir el ngfor directamente, por ejemplo, tienes tu contenido dinámico que recibe el ngfor, mételo todo a un componente aparte y aplica la directiva.

Lo que hace: es necesario ejecutar la función de iniciación cuando se crea un componente, pero como el ngfor es muy probable que no existan los elementos cuando se crea su padre, o es probable que los elementos dentro del ngFor cambien si el arreglo cambia, entonces los elementos que se bindearon ya no existen, aunque sea la misma información.

Por lo cual, todos los componentes que uso en un ngFor o que se van a cargar de manera dinámica por un request http, por ejemplo, los meto dentro de componentes individuales con el decorador

Debería de funcionar aunque sea la versión 17. Yo también estoy usando la versión 17 en un proyecto y utilicé el mismo decorador, aunque no estoy utilizando standalone components. Quizá están faltando los imports de flowbite? Podría ser una buena idea que compartas tu componente esqueleto y ver si puedo replicar el error en mi proyecto

Tu sugieres hacer el HTTP request adentro del componente que contiene el ngfor? O sugieres que se le pase la data al componente a traves de input data binding?

Dejame ver si puedo hacer un esqueleto con API y todo para que puedas replicarlo. Muchas gracias por tu ayuda @OmarMtya

La mejor idea sería que hagas un solo request HTTP por fuera, que sería el contenedor, y hacer un ngFor de los elementos que quieras repetir, pero que este for loop sea un componente personalizado con el decorador en el componente. Así cada componente ejecuta la función de initFlowbiteFix y se arregla el problema cada que se redibujan los elementos.

@juanpabloguerra16
Copy link

juanpabloguerra16 commented Jun 26, 2024

La mejor idea sería que hagas un solo request HTTP por fuera, que sería el contenedor, y hacer un ngFor de los elementos que quieras repetir, pero que este for loop sea un componente personalizado con el decorador en el componente. Así cada componente ejecuta la función de initFlowbiteFix y se arregla el problema cada que se redibujan los elementos.

@OmarMtya
Aqui te dejo un proyecto de prueba para que puedas replicar el error. En este caso nisiquera estoy haciendo una llamada HTTP. Simplemente al condicionar un nodo usando ngif ya no funciona luego flowbite. Intente agregar tu decorador y tampoco. Dejame saber que consigues.

https://github.com/juanpabloguerra16/flowbite-angular-app

@juanpabloguerra16
Copy link

@OmarMtya no se si pudiste ver mi mensaje? Saludos

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment