I have the following tippy where on hover an Ajax call goes and fetches the data, Creates the content and shows it on. But it does not work for dynamic content because on page load the
<span class="more-tags otherPostTags" data-postId="{{$post->id}}">...</span>
comes static on page, But also it comes dynamic in a tab.
So the below code works for static
<span class="more-tags otherPostTags" data-postId="{{$post->id}}">...</span>
but does not work for dynamic.
<div id="template" style="display: none;">
Loading a new image...
</div>
<span class="more-tags otherPostTags" data-postId="{{$post->id}}">...</span>
Tippy jquery :
const template = document.querySelector('#template');
const initialText = template.textContent;
const tip = tippy('.otherPostTags', {
animation: 'shift-toward',
arrow: true,
html: '#template',
onShow() {
const content = this.querySelector('.tippy-content')
if (tip.loading || content.innerHTML !== initialText) return
tip.loading = true
node = document.querySelectorAll('[data-tippy]');
let id = node[0].dataset.postid;
$.ajax({
url: '/get/post/'+id+'/tags',
type: 'GET',
success: function(res){
let preparedMarkup = '';
res.tags.map(function(item) {
preparedMarkup +=
'<span class="orange-tag" style="background-color: '+item.color+'">'+
item.name +
'</span>';
});
content.innerHTML = preparedMarkup;
tip.loading = false
},
error: function(error) {
console.log(error);
content.innerHTML = 'Loading failed';
tip.loading = false
},
});
},
onHidden() {
const content = this.querySelector('.tippy-content');
content.innerHTML = initialText;
},
popperOptions: {
modifiers: {
preventOverflow: {
enabled: false
},
hide: {
enabled: false
}
}
}
});
What am i missing here ?
This changed in a newer Tippy Version.
You need to import the delegate
method from tippy.js
:
import { delegate } from 'tippy.js';
Than initiate your tippy tooltips with the delegate method on a root element and set the selector of the elements that will have the actual tooltips via the target
prop:
delegate( '#root', {
target: '[data-tippy-content]'
} );
Make sure that the #root
element actually exists in your App or use anything else like body
for example. Then make sure to give the actual elements the data-tippy-content
attribute or change the target
selector accordingly.
If you want Tippy to activate on new elements, you need to use event delegation. The Tippy documentation covers this (frustratingly, without an anchor to link to; search for "event delegation"). You use a parent container element and then tell Tippy what selector to use to match child elements. The example from the docs is:
tippy('#parent', {
target: '.child'
})
...so for your example, use the container all the .otherPostTags
elements are in (document.body
in the worst case) and use .otherPostTags
as the target
:
tippy('selectorForParentElement', {
target: '.otherPostTags'
});
Live Example:
tippy('#container', {
target: '.otherPostTags'
});
var counter = 0;
var timer = setInterval(function() {
++counter;
var tag = document.createElement("span");
tag.title = "Tip for span #" + counter;
tag.className = "otherPostTags";
tag.innerHTML = "Span #" + counter;
document.getElementById("container").appendChild(tag);
if (counter === 6) {
clearInterval(timer);
}
}, 250);
.otherPostTags {
color: white;
background-color: #2020FF;
border: 1px solid black;
padding: 2px;
margin-left: 2px;
margin-right: 2px;
border-radius: 4px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/tippy.js/2.5.4/tippy.css" rel="stylesheet"/>
<div id="container"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tippy.js/2.5.4/tippy.min.js"></script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With