Closed AlexandreBonneau closed 6 years ago
remove the id
prop from the component
Thanks @KABBOUCHI, this indeed fixed it.
Just so I understand why it was bugging, why is declaring id
as a prop a problem?
Is there any reserved prop name we should not use?
Perhaps a small mention about that limitation in the documentation could help other users?
Thank you again :+1:
I don't know :), but you can use id
as a prop if you use it inside the template
https://codepen.io/KABBOUCHI/pen/aYdJYE?editors=1010
I'll check it later and add it in the docs if needed
edit: because the component was expecting it as a prop
not as a attribute
, i guess its the correct behavior, if u disagree u can create a issue here vue
I'm good, thanks for your time and awesome component :)
Well, I tried to fix the bug is my real code based on those codepen snippets, however vue-tippy still does not use the generated components as tooltips.
I've narrowed down the cause of that to a simple thing I guess; in the createTippy()
function, I modified the code to:
if (opts.html) {
if (opts.reactive) {
console.log('Vue-tippy: html and reactive prop detected...'); //DEBUG
opts.html = document.querySelector(opts.html);
console.log('opts.html:', opts.html); //DEBUG
} else {
if (document.querySelector(opts.html)._tipppyReferences) {
document.querySelector(opts.html)._tipppyReferences.push(el);
} else {
document.querySelector(opts.html)._tipppyReferences = [el];
}
}
}
and whenever I generate new object on which a tooltip should be shown, I see this in the console:
opts.html: null
It looks like the v-tippy
directive is called before all the components have time to be generated by Vue.
Would there be a way to prevent that? Perhaps run createTippy()
in a nextTick
?
I'm not sure how I could create a codepen that reproduce that behavior (my code is pretty huge right now, and I'm not sure at which point the delay is great enough that it makes vue-tippy bug, sorry.
Ok so, I modified the directive so that createTippy()
is always called on the nextTick
using:
Vue.directive('tippy', {
inserted: function inserted(el, binding, vnode) {
Vue.nextTick(function() {
createTippy(el, binding, vnode);
});
},
unbind: function unbind(el) {
el._tippy && el._tippy.destroy();
},
componentUpdated: function componentUpdated(el, binding, vnode) {
var opts = binding.value || {};
var oldOpts = binding.oldValue || {};
if (el._tippy && JSON.stringify(opts) !== JSON.stringify(oldOpts)) {
Vue.nextTick(function() {
createTippy(el, binding, vnode);
});
}
That almost work!
When using that, it correctly render the first component in the list and displays it correctly as a tooltip, however the subsequent components are just always displayed, except their arrow which is displayed like it should on hover.
I'm investigating.
Using the nextTick
hack, when I continue to add new elements that should have a tooltip component added to them, then hover over those with the mouse, I correctly see the tooltips .tippy-popper
appear:
<div class="tippy-popper" role="tooltip" id="tippy-15" style="z-index: 9999;
visibility: visible; position: absolute; top: 0px; left: 0px; will-change: transform;
transition-duration: 350ms; transform: translate3d(164px, 1249px, 0px);"
data-html="" tabindex="-1" x-placement="top">
<div class="tippy-tooltip light-theme operation-theme"
data-size="regular"
data-animation="fade"
data-state="visible"
data-interactive=""
data-template-id="#opTooltip-3-opTypeFoo"
style="transition-duration: 250ms; top: 0px;">
<div class="tippy-arrow" style="left: 0px;"></div>
<div class="tippy-content"></div>
</div>
</div>
...however only the arrows are shown since <div class="tippy-content"></div>
is always empty.
Would you know what would trigger the fact that .tippy-content
is empty? (while the component is generated and drawn correctly)
To be sure that using nextTick()
would solve the problem that the html selector would try to select non-existent elements, I added some console.log()
here:
Vue.directive('tippy', {
inserted: function inserted(el, binding, vnode) {
Vue.nextTick(function() {
console.log('inserted:createTippy:', el, binding, vnode); //DEBUG
console.log('binding.value.html:', binding.value.html); //DEBUG
console.log('The selected element:', document.querySelector(binding.value.html));
createTippy(el, binding, vnode);
});
},
and yes, I can see that the correct html is selected when the directive is 'inserted'.
I'm not sure why some components are rendered in the source directly and not in a .tippy-popper
element.
I'm not sure what's the problem, if you can reproduce it I'm happy to help
Me neither unfortunately.
Would you know where the .tippy-content
is supposed to be generated?
Ok so I'm not entirely sure I managed to correctly extract the faulty code from my codebase, but here is a codesandbox where adding operations to the table should also add a tooltip component, but the latter is not displayed in a tooltip.
Feel free to ping me if you want to discuss that in live (I'm on the AutoNumeric gitter if needed).
they don't have the same id
I shortened the ids (removed the date from id, plz find a better way, duplicate keys may occurred)
but the problem still exists, because they don't have the same loop.
fixed by adding Vue.nextTick
, please update to v2.0.9
i suggest to rewrite and merge paymentSchedule
, operations
and operationIcons
Thanks for the utterly speedy response :) I'll see if that fix the original problem and report back.
Thank you again!
Well, bummer, I'm back to square one since in my real code I only generated the ids with the term count and the operation type, not with the date. :cry:
With 2.0.9 I see the same problem I described 6 days ago, ie. only the very first tooltip is correctly generated, while the other components are just displayed in the html page (and when hovering over the elements that should have shown the tooltips, only the arrow is shown and in the appearing #tippy-99
element, the .tippy-content
element is empty).
About the v2.0.9
, to be more consistent with Vue.nextTick()
usage, perhaps you can also add it to the componentUpdated()
function too like so?:
componentUpdated(el, binding, vnode) {
const opts = binding.value || {};
const oldOpts = binding.oldValue || {};
if (el._tippy && (JSON.stringify(opts) !== JSON.stringify(oldOpts))) {
Vue.nextTick(() => {
createTippy(el, binding, vnode);
});
}
if (el._tippy && opts.show) {
el._tippy.show();
} else {
if (el._tippy && !opts.show && opts.trigger === 'manual') {
el._tippy.hide();
}
}
}
plz update and retry
Well, I already am editing the vue-tippy source (and the tippy and popper one too) to try to find why it's not working as intended. No luck so far.
With v2.0.10
, I still get the same problem.
I'm having trouble using my debugger on the v-tippy directive/popper library to see what exactly is going on, because when I just console.log
the ids and the html elements used for the tippy content, everything is fine.
I suspect the console is lying (as it almost always does when it comes to displaying objects and arrays). On your end, do you manage to debug (step by step) vue-tippy? (I'm using PhpStorm)
Please make sure every loop has :key
I had a :key
already in the components that are used as tooltips:
<operation-tooltip
v-for="ope in operations"
:key="`${ope.term}-${ope.type}`"
:id="`opTooltip-${ope.term}-${ope.type}`"
/>
..however I did not on the elements on which the v-tippy
directive was on.
Since I have a special configuration where the v-for
is on a template (and you can't :key
a template otherwise you get the <template> cannot be keyed. Place the key on real elements instead.
error message, I now use (per this thread):
<template v-for="icon in operationIcons">
<template v-if="inOperations(term.term, icon.type)">
<svg :class="{
icon : true,
past : isPastOp(term.term),
future: isFutureOp(term.term),
}"
v-tippy="{
html : `#opTooltip-${term.term}-${icon.type}`,
delay : [150, 200],
theme : 'light operation',
interactive: true,
reactive : true,
sticky : true,
}"
:key="`${term.term}-${icon.type}`"
>
<use :xlink:href="svgIcon(icon.iconName)"></use>
</svg>
</template>
<template v-else>
<svg class="icon"
:key="`${term.term}-${icon.type}`"
><use :xlink:href="svgIcon(icon.iconName)"></use></svg>
</template>
</template>
But even with those keys, only the first tooltip is correctly added. I'll keep investigating..
remove the template
tag and put v-if
and v-else
on the svg
element
Done. It's a bit clearer that way indeed, unfortunately that does not fix the problem.
So, since I somehow can't hit any breakpoints in libraries in the node_modules
directory, I had to resort to the annoyingly long console.log()
way of debugging.
I've littered the dist/vue-tippy.js file with lots for console logging, and so far what I can tell is that at the end of the createPopperElement()
function, the .tippy-content
element is correctly set with the html node from the tooltip component (since I can see that popper.firstChild.childNodes[1].childElementCount
is equal to 1
).
In createTooltips()
, just after initializing the Tippy
element in the tippy
variable, tippy.popper.firstChild.childNodes[1].childElementCount
is also equal to 1
.
So far so good.
However if I console.log(tippy)
as that same place, and since Chrome/Firefox only display a reference to the objects in the console (and not their values when they are logged), I can see that once my page is loaded, the tippy.popper.firstChild.childNodes[1].childElementCount
is equal to 0
when expanding that object manually.
(Note: the very first tooltip generated is the only one having a populated .tippy-content
element)
The question is; what happens to those .tippy-content
elements between the point where there are (correctly) generated by popper, and when Vue has finished generating the page (and somehow their content is emptied, apparently)?
I'm not sure how or what more I could inspect here. Any ideas?
I'll close this due to inactivity.
For info, I still haven't fixed the problem nor found the cause of why vue-tippy refuses to correctly generate the tooltip.
Would you have more info about the last questions I asked by any chance?
Can you reproduce the problem? so i can check the problem? or can you share ur code privately?
Starting from my simple tooltip example where a tooltip component is cloned as many times as needed, I tried modifying the underlying data in order to generate a dynamic amount of elements (and therefore tooltips components), however it seems
vue-tippy
stops transforming those components in tooltips.I first tried a simple synchronous version, however while I added the async version, it broke and I can't find a way to display the tooltips anymore. Whoops! :smirk:
Then I created an asynchronous version where the tasks can either be added synchronously or asynchronously, in order to test if the tooltip components are correctly created.
As you can see, the tooltip components are correctly created, but directly displayed instead of being hidden.
Would you know if that's a bug and how to fix it?