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

Singleton composition API not working with conditional content #312

Open
mattbryson opened this issue Jun 26, 2024 · 1 comment
Open

Singleton composition API not working with conditional content #312

mattbryson opened this issue Jun 26, 2024 · 1 comment

Comments

@mattbryson
Copy link

I'm trying to group a few Buttons using the useSingleton approach.

This works when the Buttons are present when the component mounts, but if they are conditionally added later, they just use the default Tippy settings, not the singleton settings.

See a working demo here

It does work if you use the <tippy> and <tippy-singleton> components, but not if you mix the v-tippy directive, and the useSingleton composition API as per the example https://vue-tippy.netlify.app/flavor/composition-api#example-1-1

I have tried calling useSingleton after they are added, have tried delaying adding them to the instances array etc etc but nothing I do appears to work.

Any ideas on how to get this working?

@mattbryson
Copy link
Author

I found what was going on. When using the directive, it uses the mounted lifecycle hook, but that is for the parent component, NOT the element that the directive is on.

So for elements added after mounted they are not added to singleton group.

For now I have a patch to get it working for anyone with this issue, which I can make into a pull request at some point.

Add this file to your project.

import { DirectiveHook, ObjectDirective, Ref, ref, watchEffect } from 'vue';

import { CreateSingletonProps, Instance } from 'tippy.js';
import { directive, useSingleton as orig_useSingleton } from 'vue-tippy';


/**
 * Custom useSingleton function to keep a reference to the instances it manages.
 * Tippy.js does not expose this (that I can see), so we ned to to hold on to it
 * externally, and then re apply it when it changes
 */
function useSingleton(opts?:Partial<CreateSingletonProps>) {

  const instances:Ref<Instance[]> = ref([]);
  const data = orig_useSingleton(instances, opts);

  watchEffect(() => {
    if(data.singleton.value) {
      data.singleton.value.setInstances( instances.value );
    }
  });

  return {
    ...data,
    instances
  };
}

// Clone the exisitng Tippy directive, and swap the mounted for created....
const vTippyPatched:ObjectDirective & { orig_mounted?:DirectiveHook<any, null, any> } = {...directive};
vTippyPatched.orig_mounted = vTippyPatched.mounted; 
delete vTippyPatched.mounted; 

vTippyPatched.created = (el, binding, vnode, prevVNode) => {  

    const opts = typeof binding.value === "string" ? { content: binding.value } : binding.value || {}

    // call the orig mounted logic
    if(vTippyPatched.orig_mounted) {
      vTippyPatched.orig_mounted(el, binding, vnode, prevVNode);
      // if we have a singleton options, append this to its instance list
      if(el._tippy && opts.singleton) {
        opts.singleton.instances.value.push(el._tippy);
      }
  }
}

export { useSingleton, vTippyPatched };

To replace the current v-tippy directive with this one, you can do the following....

import { vTippyPatched } from '@app/directives/tippyPatch';

.....

app.use(VueTippy, {directive: 'tippy-orig'});
// Patch the Tippy directive to support singleton
app.directive('tippy', vTippyPatched);

And then to use it, do the following....

<script>

import { useSingleton } from '@app/directives/tippyPatch';

const singleton = useSingleton({moveTransition: 'transform 0.2s ease-out', delay:[1000,500]});

</script>

<template>
    <button  v-tippy="{content:'One', singleton}" >One</button>
    <button  v-tippy="{content:'Two', singleton}" >Two</button>
    <button  v-tippy="{content:'Three', singleton}" >Three</button>
</template>

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