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

Mixin functions (i.e. $bvToast, $bvModal) do not work on Vue 3 #7111

Open
Morgul opened this issue Jan 18, 2023 · 11 comments
Open

Mixin functions (i.e. $bvToast, $bvModal) do not work on Vue 3 #7111

Morgul opened this issue Jan 18, 2023 · 11 comments

Comments

@Morgul
Copy link

Morgul commented Jan 18, 2023

Describe the bug

When running with @vue/compat in { MODE: 2 }, it appears that any functions added to Vue instance by a mixin are not available. This includes $bvToast and $bvModal.

Steps to reproduce the bug

  1. Run in Vue 3 mode with @vue/compat.
  2. Inside of a component, attempt to access this.$bvToast.
  3. It does not exist.

Expected behavior

When running with Vue 3, these functions should appear. (It's particularly bad for $bvToast, as there's no other way to dynamically create toasts.)

Versions

Libraries:

  • BootstrapVue: 2.23.1
  • Bootstrap: 4.6.1
  • Vue: 3.2.45
  • Vue Compat: 3.2.45

Environment:

  • All

Additional context

I'm attempting to upgrade my application to Vue 3 (as an exploratory exercise) and I cannot, for the life of me work out how to use functions added by mixins. Without that, I can't convert the parts of my application that use toasts; they're just broken.

@EagleTsui
Copy link

Hi,

I face same problem, I cannot get bvModal by composition API. In my investigation, the following will work for me.
const bvModal = (getCurrentInstance() as any).ctx._bv__modal as BvModal

@Morgul
Copy link
Author

Morgul commented Jan 20, 2023

@EagleTsui Thank you! getCurrentInstance() was the magic I was missing.

So, for other people who run into this, you have to call getCurrentInstance() from inside of the component. This is how I handled it, inside of my <script> tag:

import { getCurrentInstance } from 'vue';
import { BvToast } from 'bootstrap-vue';

const instance = (getCurrentInstance() as any);

setTimeout(() =>
{
    // The timeout seems to be need, otherwise _bv__toast is undefined.
    const bvToast = instance.ctx._bv__toast as BvToast;
}, 100);

@Morgul
Copy link
Author

Morgul commented Jan 20, 2023

For anyone who comes across this, I should mention, getCurrentInstance was removed in Vue3: vuejs/docs#1422 (comment).

Also, _bv__toast (or anything like that) is an internal name used inside the BootstrapVue code, and could possibly change in the future (though not super likely). I would hesitate to rely on this work around in production for anything critical, but this does seem to work.

@EagleTsui
Copy link

EagleTsui commented Jan 20, 2023

@EagleTsui Thank you! getCurrentInstance() was the magic I was missing.

So, for other people who run into this, you have to call getCurrentInstance() from inside of the component. This is how I handled it, inside of my <script> tag:

import { getCurrentInstance } from 'vue';
import { BvToast } from 'bootstrap-vue';

const instance = (getCurrentInstance() as any);

setTimeout(() =>
{
    // The timeout seems to be need, otherwise _bv__toast is undefined.
    const bvToast = instance.ctx._bv__toast as BvToast;
}, 100);

You need place code in setup or onMounted then you can remove the setTimeout

@Morgul
Copy link
Author

Morgul commented Jan 20, 2023

@EagleTsui That makes sense. And just tested, that worked perfectly.

@Flecart
Copy link

Flecart commented Jun 9, 2023

This is so weird, i was trying eagleTsui's temporary fix, but if i console log the property exists, but when i try to access it says it's undefined. I'm losing my mind!!!!

If i dump a Object.keys, the key is not present. But why if i console log that it is present!

@marianocodes
Copy link

This worked for me #4472

@mzuvin
Copy link

mzuvin commented Sep 17, 2023

not working

image

@gtempesta-pixartprinting
Copy link

gtempesta-pixartprinting commented Mar 7, 2024

I didn't test it with BvToast but I've found a way with BvModal.

I think that what made it work is the use of mounted together with nextTick, because at the beginning a log of the full instance.ctx._bv__modal yielded undefined, but when logging only instance.ctx I was able to see the _bv__modal property. This made me realise it was just a timing/rendering issue.

import { getCurrentInstance, nextTick } from 'vue';

export default {
  data() {
    return {
      instanceModal: null,
    };
  },
  methods: {
    openFirstOrderModal() {
      this.instanceModal.show('modal-first-order');
    },
  },
  mounted() {
    const instance = getCurrentInstance();
    nextTick(() => {
      this.instanceModal = instance.ctx._bv__modal;
    });
  },
}

Libraries:

  • BootstrapVue: 2.23.1
  • Bootstrap: 4.3.1
  • Vue: 3.3.13
  • Vue Compat: 3.3.13

Update

After posting this I've tried a few more times and this solution is completely unstable: I have several modals in the same page, and on different refreshes one modal works and another doesn't.

Besides, the one that works seems to have also this.$bvModal variable defined, so this solution has become useless at this point.

Update 2

A possible solution for modals is to emit an event on the root.

Personally I've tried to avoid using it because it reduces predictability, but it may work as a temporary solution.

this.$root.$emit('bv::show::modal', 'modal-first-order');

@bob-lee
Copy link

bob-lee commented Apr 13, 2024

had this issue with vue@2.7, getCurrentInstance gave me a proxy that has _bv__toast:

<script setup>
import { getCurrentInstance } from 'vue'

const instance = getCurrentInstance()
console.log('getCurrentInstance', instance.proxy._bv__toast)
// ...

@z1m1n
Copy link
Contributor

z1m1n commented Apr 23, 2024

this['_bv__toast'].show('reload-toast'); works like a charm

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

8 participants