Javascript: Tippy.js не работает для динамического контента
У меня есть следующий совет, где при наведении Ajax-вызов идет и получает данные, создает содержимое и показывает его. Но это не работает для динамического контента, потому что при загрузке страницы
<span class="more-tags otherPostTags" data-postId="{{$post->id}}">...</span>
На странице появляется статическое значение, но на вкладке также отображается динамическое.
Таким образом, приведенный ниже код работает для статического
<span class="more-tags otherPostTags" data-postId="{{$post->id}}">...</span>
но не работает для динамического.
<div id="template" style="display: none;">
Loading a new image...
</div>
<span class="more-tags otherPostTags" data-postId="{{$post->id}}">...</span>
Типпи 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
}
}
}
});
Что мне здесь не хватает?
3 ответа
Если вы хотите, чтобы Tippy активировал новые элементы, вам нужно использовать делегирование событий. Документация Tippy покрывает это (разочарование, без привязки к ссылке; поиск "делегирование события"). Вы используете родительский элемент контейнера, а затем сообщаете Tippy, какой селектор использовать для соответствия дочерним элементам. Пример из документации:
tippy('#parent', {
target: '.child'
})
... так что для вашего примера, используйте контейнер все .otherPostTags
элементы находятся в (document.body
в худшем случае) и использовать .otherPostTags
как target
:
tippy('selectorForParentElement', {
target: '.otherPostTags'
});
Живой пример:
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>
Это изменилось в более новой версии Типпи.
Вам необходимо импортировать delegate
метод от tippy.js
:
import { delegate } from 'tippy.js';
Затем инициируйте свои типичные всплывающие подсказки с помощью метода делегата для корневого элемента и установите селектор элементов, которые будут иметь фактические всплывающие подсказки через target
опора:
delegate( '#root', {
target: '[data-tippy-content]'
} );
Убедитесь, что #root
элемент действительно существует в вашем приложении или используйте что-нибудь еще, например body
например. Затем не забудьте указать фактическим элементамdata-tippy-content
атрибут или изменить target
селектор соответственно.
Я смог сделать это с Laravel следующим образом:
@for($i = 0; $i < 10; ++$i)
<br /> <button data-tippy-content="<img src='https://picsum.photos/300/300?random={{$i + 1}}' />">Text</button>
<br />
@endfor
<script>
tippy('[data-tippy-content]', {
trigger: 'click',
});
</script>