-
-
Save OmarMtya/9ce68c563893d1c774f11a94ea73a31c to your computer and use it in GitHub Desktop.
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); | |
}); | |
}); | |
}); | |
} |
this hack is awesome
Thanks! Just as a comment, you want to execute an specific function to hide the modals/drawers. This is the function:
closeModals(){ var event = new KeyboardEvent('keydown', { key: 'Escape' }); document.body.dispatchEvent(event); }
Make sure to execute it when the user clicks on a submit button or close the modal instead of the data-modal-hide attribute, that would help a lot with the possible double backdrop when you use it with dynamic elements in HTML.
este truco es increible
¡Gracias! Solo como comentario, desea ejecutar una función específica para ocultar los modales/cajones. Esta es la función:
closeModals(){ var event = new KeyboardEvent('keydown', { key: 'Escape' }); document.body.dispatchEvent(event); }
Asegúrese de ejecutarlo cuando el usuario haga clic en un botón de enviar o cerrar el modal en lugar del atributo data-modal-hide, eso ayudaría mucho con el posible doble fondo cuando lo use con elementos dinámicos en HTML.
Could you make an example of how to use that method in modals and sidebar?
este truco es increible
¡Gracias! Solo como comentario, desea ejecutar una función específica para ocultar los modales/cajones. Esta es la función:
closeModals(){ var event = new KeyboardEvent('keydown', { key: 'Escape' }); document.body.dispatchEvent(event); }
Asegúrese de ejecutarlo cuando el usuario haga clic en un botón de enviar o cerrar el modal en lugar del atributo data-modal-hide, eso ayudaría mucho con el posible doble fondo cuando lo use con elementos dinámicos en HTML.Could you make an example of how to use that method in modals and sidebar?
En lugar de utilizar el data-modal-toggle o cualquier etiqueta de ese estilo, tus botones que ejecuten con un click esa función.
<button (click)="closeModals()>Cerrar</button>
No he utilizado el sidebar, pero me imagino que si se cierra presionando la tecla Escape, seguramente funcione.
Suerte
@OmarMtya por alguna razon no me functiona tu truco.
Estoy mostrando contenido dinamico usango ngFor y por lo tanto el modal esta adentro y estoy asignando un ID diferente a cada modal. Tambien le agregue el decorado que creaste a la clase de mi componente y aun asi no abre el modal. Tienes alguna recomendacion? Saludos
@OmarMtya por alguna razon no me functiona tu truco.
Estoy mostrando contenido dinamico usango ngFor y por lo tanto el modal esta adentro y estoy asignando un ID diferente a cada modal. Tambien le agregue el decorado que creaste a la clase de mi componente y aun asi no abre el modal. Tienes alguna recomendacion? Saludos
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
Gracias Omar. Tiene sentido. Separe el component que esta haciendo la solicitud HTTP a un componente diferente y agregue el decorador al componente padre pero aun asi no funciono. No se si es porque estoy usando la ultima version de angular y componentes independientes, entonces no tengo app.module.ts en mi aplicacion
Gracias Omar. Tiene sentido. Separe el component que esta haciendo la solicitud HTTP a un componente diferente y agregue el decorador al componente padre pero aun asi no funciono. No se si es porque estoy usando la ultima version de angular y componentes independientes, entonces no tengo app.module.ts en mi aplicacion
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
The strategy of OmaMyta worked perfectly in my project; I was having trouble displaying dropdowns. I'm using Angular 17 with the standalone version. Initially, the solution didn't work because I was calling the directive in my AppComponent, and it was only initialized once. After realizing this mistake, I chose to use the initFlowBite provided by flowBite, and that also worked.
The structure of the component was as follows:
import { Component } from '@angular/core';
import { initFlowbite } from 'flowbite';
@Component({
selector: 'app-navbar',
standalone: true,
imports: [],
templateUrl: './navbar.component.html',
styleUrl: './navbar.component.scss'
})
export class NavbarComponent {
ngAfterViewInit() {
initFlowbite();
}
}
Hola, talvez alguien pudo resolver de que se muestren los modals sin tener que recargar la página, aunque no hay problemas con los que no están en un @for, el problema en cuando se lo llama por datos de una tabla...
I am facing the same issue on my angular 16 and i am kind of confused how to use this hack. Currently i have this in my app.component.ts :`import {Component, OnInit} from '@angular/core';
import {initFlowbite, initModals, initPopovers, initTabs, initTooltips} from 'flowbite';
@component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit{
title = 'KhetSeGhar';
constructor() {
}
ngOnInit() {
console.log('hi from app')
initFlowbite();
initModals();
initPopovers();
initTabs();
initTooltips();
}
`
The strategy of OmaMyta worked perfectly in my project; I was having trouble displaying dropdowns. I'm using Angular 17 with the standalone version. Initially, the solution didn't work because I was calling the directive in my AppComponent, and it was only initialized once. After realizing this mistake, I chose to use the initFlowBite provided by flowBite, and that also worked. The structure of the component was as follows:
import { Component } from '@angular/core'; import { initFlowbite } from 'flowbite'; @Component({ selector: 'app-navbar', standalone: true, imports: [], templateUrl: './navbar.component.html', styleUrl: './navbar.component.scss' }) export class NavbarComponent { ngAfterViewInit() { initFlowbite(); } }
Gracias crack tambien tenia ese error pero con un Dropdown menu de flowbite le agrege el initFlowbite al componente y hice la importacion y santo remedio epico 🗣️🗣️🗣️🔥🔥🔥
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[] = [];
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
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.
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.
@OmarMtya no se si pudiste ver mi mensaje? Saludos
this hack is awesome