Closed stanislavhannes closed 2 years ago
i have this issue too on a simple vue 3 project with either vite or webpack
same issue in Blazor web assembly flowbite.bundle.js exist in client side but not working at all
The way the flowbite.bundle.js
works is that it looks for the data attributes and then applies event listeners, this means that the JS needs to have an already rendered DOM to make it work.
We are aware of the compatibility issues regarding virtual DOM based libraries and frameworks, we're trying to find solutions.
Please take into account that the other non-interactive components (ie. buttons, alerts, badges) still work regardless of the JS file.
A simple way would be to encapsulate the event listeners into a public function (let's say Tooltip.start();
) and let the user call it in their own listeners.
document.addEventListener("dom-reload", function() {
Tooltip.start();
});
Unfortunately this makes the library unusable in what amounts to i'd wager 80% of modern web applications :/ I'm making a hack like this to make it work, but i'd suggest a more performant solution down the line.
Edited the flowbite.bundle.js with the following addition:
const liveQueries = [];
const container = document.getElementById("root");
const observer = new MutationObserver((records) => {
liveQueries.forEach((q) => q());
});
observer.observe(container, {
childList: true,
subtree: true,
});
const liveQuerySelector = (selector, callback) => {
const update = () => {
const found = container.querySelectorAll(selector);
found.forEach(callback);
};
liveQueries.push(update);
};
And replaced each of the 5 top level occurences of
document.querySelectorAll(*some selector*).forEach(function
with
liveQuerySelector(*some selector*, function
It seems that references to elements are still sometimes lost and this might lag on large DOMs, but It's better than nothing.
The code is also up on gist: https://gist.github.com/aleqsio/6273a99f18ff8f494ca7337d8be7d955
A simple way would be to encapsulate the event listeners into a public function (let's say
Tooltip.start();
) and let the user call it in their own listeners.document.addEventListener("dom-reload", function() { Tooltip.start(); });
I'll look into this solution tomorrow. Thanks.
Unfortunately this makes the library unusable in what amounts to i'd wager 80% of modern web applications :/
I'm making a hack like this to make it work, but i'd suggest a more performant solution down the line.
Edited the flowbite.bundle.js with the following addition:
const liveQueries = []; const container = document.getElementById("root"); const observer = new MutationObserver((records) => { liveQueries.forEach((q) => q()); }); observer.observe(container, { childList: true, subtree: true, }); const liveQuerySelector = (selector, callback) => { const update = () => { const found = container.querySelectorAll(selector); found.forEach(callback); }; liveQueries.push(update); };
And replaced each of the 5 top level occurences of
document.querySelectorAll(*some selector*).forEach(function
with
liveQuerySelector(*some selector*, function
It seems that references to elements are still sometimes lost and this might lag on large DOMs, but It's better than nothing.
The code is also up on gist:
https://gist.github.com/aleqsio/6273a99f18ff8f494ca7337d8be7d955
Thanks for the workaround and info.
We are looking into a solution to make the event listeners work overall.
We also started a project where we will build separate React and Vue components.
No worries, thanks for looking into this. Hope there'll be an official solution soon :) I think even exporting the individual functions as onClick handlers would be a significant step up in functionality while being a hopefully small workload.
With the v1.3.0 release of Flowbite we have now solved the problem of event listeners not registering with front-end libraries and frameworks such as React.js and Vue.
Please check out this guide on how to use Tailwind CSS and Flowbite inside a Vue project.
PS: there's no official Vue package just yet, we're working on that. But interactive elements like tooltips and dropdowns should now work.
You're using document.addEventListener('DOMContentLoaded'
so it still won't work anytime there is a programmatic change in DOM after initial load (i think).
What about cases like using react-router - will all interactive components not work on react router pages?
What about initial loading spinners?
I'm either missing something and integrated this wrong, or this still doesn't work for any real life use in react :(
Hey @aleqsio,
Can you send me a repo to test that out?
Thanks!
PS: we'll launch a standalone React and Vue.js component library at the beginning of Q2, so all of these problems will be solved and you won't need to use the data attributes anymore.
You're using
document.addEventListener('DOMContentLoaded'
so it still won't work anytime there is a programmatic change in DOM after initial load (i think). What about cases like using react-router - will all interactive components not work on react router pages? What about initial loading spinners?I'm either missing something and integrated this wrong, or this still doesn't work for any real life use in react :(
+1 , not working vue-router , only index.vue
vite + vite-plugin-vue-layouts + vite-plugin-pages + vue-router
https://github.com/MilesWuCode/my-vite-template/tree/flowbite
EX: working http://localhost:3000
not working http://localhost:3000/todo
I'm having the same issue with basic html5 setup (using rails 7)
The dropdown no longer triggers after a page change. I have to refresh the page.
I also have this problems, but with dropdown elements Vue 3 + Laravel 8, flowbite 1.3.4 I'm creating table using axios. In one colum I have dropdown with unique "id". But dropdowns isn't work in it. Outside of element everything works fine. When im using DaizyUI, dropdowns works. But I have some problems with styling this, so I want use flowbite. Is any solutions now?..
UPD: Like temporary solution I use dropdowns form Headless UI. This dropdowns work fine
Still having this same problem
PS: we'll launch a standalone React and Vue.js component library at the beginning of Q2, so all of these problems will be solved and you won't need to use the data attributes anymore.
@zoltanszogyenyi ETA for Vue.js version?
I'm also having problems getting interactive components to work. The setup instructions for vue work, but when vue-rpouter
is added to the project, everything stops again.
Same issue here,
when using Vue3 reactivity (v-if) the event listener "breaks" and won't pickup any changes.
I'm using flowbite: 1.4.7 vue: 3.2.33
Some context:
<script setup>
import { Link } from '@inertiajs/inertia-vue3'
// import { Dropdown } from 'flowbite'
import Flowbite from 'flowbite'
import { Inertia } from '@inertiajs/inertia'
Inertia.on('finish', () => {
document.querySelectorAll('[data-dropdown-toggle]').forEach(triggerEl => {
const targetEl = document.getElementById(triggerEl.getAttribute('data-dropdown-toggle'))
const placement = triggerEl.getAttribute('data-dropdown-placement')
Flowbite.Dropdown(targetEl, triggerEl, {
placement: placement ? placement : 'bottom'
})
})
})
</script>
tho seems something is happening in the browser devtools
flowbite__WEBPACK_IMPORTED_MODULE_1___default(...).Dropdown is not a function
Some context:
<script setup> import { Link } from '@inertiajs/inertia-vue3' // import { Dropdown } from 'flowbite' import Flowbite from 'flowbite' import { Inertia } from '@inertiajs/inertia' Inertia.on('finish', () => { document.querySelectorAll('[data-dropdown-toggle]').forEach(triggerEl => { const targetEl = document.getElementById(triggerEl.getAttribute('data-dropdown-toggle')) const placement = triggerEl.getAttribute('data-dropdown-placement') Flowbite.Dropdown(targetEl, triggerEl, { placement: placement ? placement : 'bottom' }) }) }) </script>
tho seems something is happening in the browser devtools
flowbite__WEBPACK_IMPORTED_MODULE_1___default(...).Dropdown is not a function
You were close to the solution ! Here is what worked for me
<script setup>
import { Link } from '@inertiajs/inertia-vue3'
import Flowbite from 'flowbite'
import { Inertia } from '@inertiajs/inertia'
Inertia.on('finish', () => {
document.querySelectorAll('[data-dropdown-toggle]').forEach(triggerEl => {
const targetEl = document.getElementById(triggerEl.getAttribute('data-dropdown-toggle'))
const placement = triggerEl.getAttribute('data-dropdown-placement')
const dd = new Dropdown(targetEl, triggerEl, {
placement: placement ? placement : 'bottom'
})
})
})
</script>
1- Dropdown is a class and not a function 2- Looks like when you import the module everything it contains is global so you can use Dropdown directly
I hope this helps !
Nice. The code isn't mine, just bring it from the Discord channel to get some help for a user. Thanks @benoit96
You're welcome @rluders
Still having the same issue.
Hey, everyone!
A new standalone Vue 3 library has been started here and @ralphschuler is the maintainer.
If you'd like to help you can contribute to the repository and reach out to me or @ralphschuler :)
any workaround? for Vue 3 + inertia js
I have this issue too... The main problem is that JS components registration is attached to DOMContentLoaded
event. Unfortunately, in some case (very light page content), the DOM finishes to load BEFORE the JS code is executed.
This is very well explained here: https://stackoverflow.com/a/39993724/1887976
A solution would be to transform this kind of code (ex for modal):
document.addEventListener('DOMContentLoaded', () => {
let modalInstances = []
document.querySelectorAll('[data-modal-toggle]').forEach(el => {
const modalId = el.getAttribute('data-modal-toggle');
const modalEl = document.getElementById(modalId);
const placement = modalEl.getAttribute('data-modal-placement')
if (modalEl) {
if (!modalEl.hasAttribute('aria-hidden') && !modalEl.hasAttribute('aria-modal')) {
modalEl.setAttribute('aria-hidden', 'true');
}
}
let modal = null
if (getModalInstance(modalId, modalInstances)) {
modal = getModalInstance(modalId, modalInstances)
modal = modal.object
} else {
modal = new Modal(modalEl, {
placement: placement ? placement : Default.placement
})
modalInstances.push({
id: modalId,
object: modal
})
}
if (modalEl.hasAttribute('data-modal-show') && modalEl.getAttribute('data-modal-show') === 'true') {
modal.show();
}
el.addEventListener('click', () => {
modal.toggle()
})
})
})
into something similar to this
const initModal = () => {
let modalInstances = []
document.querySelectorAll('[data-modal-toggle]').forEach(el => {
const modalId = el.getAttribute('data-modal-toggle');
const modalEl = document.getElementById(modalId);
const placement = modalEl.getAttribute('data-modal-placement')
if (modalEl) {
if (!modalEl.hasAttribute('aria-hidden') && !modalEl.hasAttribute('aria-modal')) {
modalEl.setAttribute('aria-hidden', 'true');
}
}
let modal = null
if (getModalInstance(modalId, modalInstances)) {
modal = getModalInstance(modalId, modalInstances)
modal = modal.object
} else {
modal = new Modal(modalEl, {
placement: placement ? placement : Default.placement
})
modalInstances.push({
id: modalId,
object: modal
})
}
if (modalEl.hasAttribute('data-modal-show') && modalEl.getAttribute('data-modal-show') === 'true') {
modal.show();
}
el.addEventListener('click', () => {
modal.toggle()
})
})
}
if (document.readyState !== 'loading') {
// DOMContentLoaded event already fired, let's perform initialization explicitely
initModal()
} else {
// DOMContentLoaded event not yet fired, attach initialization process to it
document.addEventListener('DOMContentLoaded', initModal)
}
Hey everyone,
So we started working on the Flowbite Vue component library so all Vue and Nuxt-related issues should be addressed there since the main Flowbite Library is based on event listeners and not completely compatible with libraries and frameworks such as React or Vue.js (that's why we started working on actual Vue or React components.)
Feel free to contribute to those repositories!
Hey there, I am using a fresh project with tailwind2, flowbite 1.1.1 and vue3. The backend stack ist laravel 8 (php8) with inertia.js. If I'm creating a modal inside a Vue component, then I can't open/toggle the model (data-modal-toggle="default-modal" is set to the button) . It only works, if i move the button and modal out of the component, into the final html generated site (with Blade Template Engin). It affects not only the modal, but also the alert dismiss button and basically everything that need flowbite javascript.
Has someone the same issue and know a workaround?