I'm posting here because after many hours of research and some headache I didn't find a solution to a problem with swiper JS in my website.
In my case, I have a WordPress website and I have an archive page with many listings each one with a slider (Swiper JS) that shows relevant images of the listing.
It works fine until I apply a filter to the page (Eg. select to show property with 4 beds) (so I think before I make an AJAX request).
The page reloads with AJAX and shows only relevant listings, the only problem is that the Swiper Slider doesn't work anymore, in fact, I cannot slide it.
By logic, I think I need to reinitialize Swiper after every AJAX call but as I'm not so good at AJAX I'm kind of wondering if anyone can point me into the right direction. Thank you very much.
My Swiper Code:
jQuery(document).ready(function() {
const swiper = new Swiper('.swiper', {
// Optional parameters
direction: 'horizontal',
effect: 'slide',
speed: 150,
loop: true,
observer: true,
// Navigation arrows
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
pagination: {
el: '.swiper-pagination',
},
});
});
Why don't you use swiper lazy and param-lazy-loadPrevNext ?
You're probably right. When the results container with the Swiper instances updates, Swiper needs to re-initialize the new result elements when they are attached to the DOM.
You should be able to re-use the same Swiper initializer. Just place it in a separate function. Then call that function on document load (as you are now) and when the AJAX results load, after the DOM is updated.
Example:
let swiper;
function initSwiper() {
swiper = new Swiper('.swiper', {
// Optional parameters
direction: 'horizontal',
effect: 'slide',
speed: 150,
loop: true,
observer: true,
// Navigation arrows
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
pagination: {
el: '.swiper-pagination',
},
});
}
jQuery(document).ready(function() {
initSwiper(); // <---------------
// ...
$.ajax({
url: '/ajax-url/',
dataType: "json",
type: "Post",
async: true,
data: { },
success: function (data) {
$('#results').html(data.results_html);
initSwiper(); // <---------------
},
error: function (xhr, exception) {
// Error handling
}
});
});
Related
Scenario :
When the page is rendering the products are shown and every product has a discover button. On clicking the button I want to display the gallery / slider images below that product.
Currently, when I click the first product, Swiper is showing the images. And, if I slide the images to 3rd or 4th (or any), the new product slider image is starting from that particular index i.e., from 3rd or 4th.
The configuration I used for Swiper is :
public config: SwiperConfigInterface = {
centeredSlides: true,
initialSlide: 0,
slidesPerView: 1,
loop: false,
spaceBetween: 0,
autoplay: false,
direction: 'horizontal',
keyboard: false,
navigation: true,
pagination: {
el: '.swiper-pagination',
type: 'bullets',
clickable: true
},
hashNavigation: false,
effect: 'slide'
};
And, the discover button is calling the below method :
discover(locationId) {
this.locationImages = [];
this.destinations.forEach(selectedData => {
if(selectedData._id == locationId){
selectedData.optional_images.forEach(image => {
this.locationImages.push(image)
});
}
});
console.log(this.locationImages);
}
I searched the docs and google, didn't find any reliable solution. Please suggest some answers. Thank you in advance.
Check the documentation at https://swiperjs.com/swiper-api - seems that you can use swiper.slideTo(index, speed, runCallbacks) method to revert to first (or any) slide element whenever you need, like upon changing the active product.
I have a javascript code to make a slider, and inside the slider, there are content changes when calling a method via livewire, and the problem is when calling it, the slider blows up, and the javascript code won't work.
view:
#foreach($section->children()->get() as $subSection)
<button wire:click="serviceChanger({{ $subSection->id }})">{{ $subSection->name }}</button>
#endforeach
#foreach($services as $service)
the services here changes depending on the serviceChanger method
#endforeach
javascript
<script>
var swiper = new Swiper('.swiper-container', {
slidesPerView: 1,
spaceBetween: 10,
// init: false,
pagination: {
el: '.swiper-pagination',
clickable: true,
},
breakpoints: {
640: {
slidesPerView: 1,
spaceBetween: 20,
},
768: {
slidesPerView: 2,
spaceBetween: 40,
},
1024: {
slidesPerView: 4,
spaceBetween: 50,
},
}
})
</script>
component:
public function serviceChanger($id)
{
// some logic
}
after I call the ServiceChanger, the javascript won't work when the services change.
Any Ideas?
I solve my problem by Dispatching a Browser Event at the end of the serviceChanger method
$this->dispatchBrowserEvent('contentChanged');
in the JavaScript, file Catch the event like that
window.addEventListener('contentChanged', event => {
// your JS code
});
You need to re-initialize your javaScript code when Livewire refreshes the content.
When livewire replaces the HTML in the DOM with your new HTML, none of the JS code executes
You have to manually make sure everything executes again
For More Info take a look at Livewire Event
I tried to insert swiper carousel into bootstrap modal 4 and it works only after resizing the screen.
I found the example where a guy had the same problem. He solved it using setTimeout (). The code looks:
setTimeout(function() {
var swiper = new Swiper(".swiper-container", {
loop: true,
autoplay: 10000,
grabCursor: true,
centeredSlides: true,
paginationClickable: true,
autoplayDisableOnInteraction: true
});
}, 0);
For my case it haven't worked.. Here you see my problem. Just click on the button Tap Here.
Thanks!
I am using https://swiperjs.com/ and working with Vue framework. I will explain the different scenarios:
Scenario 1 (produces bug, need a fix for this):
I am getting reviews from a GraphQL query. The answer is used to populate the swiper. This way of dynamically adding the content to the swiper gives me a bug where the slider starts at the last slide.
Scenario 2(works, but the content is manually set): I have a defined the content of reviews as a variable in my data section. Slider works as it should. Setting the data manually in all lifecycles except beforeCreate works with no bugs.
This is my the relevant code:
getProductReviews(this.$apollo, { sku: 0 })
.then(result => {
// const temp = result.data.getBVReviews.reviews;
// result.data.getBVReviews.reviews.push(temp[0]);
// result.data.getBVReviews.reviews.push(temp[1]);
this.getBVReviews = result.data.getBVReviews;
if (this.isMounted) {
this.setupReviewSlider();
}
})
.catch(error => {
console.log('Failed to load review data.');
console.log(error);
});
setupReviewSlider() {
this.reviewSlider = new Swiper('.swiper-container', {
slidesPerView: 'auto',
initialSlide: 0,
observer: true,
observParents: true,
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
});
// this.reviewSlider.on('reachEnd', () => {
// this.reviewSlider.slideTo(0, false,false);
// this.reviewSlider.autoplay = false;
// })
},
The HTML part is pretty big and it would only confuse you. I doubt that there is a need to see it but if you do just tell me.
Any ideas?
I am using the jQuery slider called Swiper in my project.
http://www.idangero.us/sliders/swiper/
I am new to programming (js / jquery). I want to execute a function, some jquery code to be more specific, whenever the first slide of the slider is active. I think their API makes this possible, but I have no idea how to use. If somebody could help, I'd appreciate. Here's their API:
http://www.idangero.us/sliders/swiper/api.php
Thanks.
I build a little demo in jsfiddle to demonstrate how to react on slide events with "swiper":
http://jsfiddle.net/KhgFX/2/
Use the Event-Callback functions by swiper, as mentioned in the API-docu.
$(document).ready(function () {
$(function () {
var mySwiper = $('.swiper-container').swiper({
mode: 'horizontal',
watchActiveIndex: true,
loop: true,
onSlideChangeStart: function (swiper) {
console.log('slide change start - before');
console.log(swiper);
console.log(swiper.activeIndex);
//before Event use it for your purpose
},
onSlideChangeEnd: function (swiper) {
console.log('slide change end - after');
console.log(swiper);
console.log(swiper.activeIndex);
//after Event use it for your purpose
if (swiper.activeIndex == 1) {
//First Slide is active
console.log('First slide active')
}
}
});
})
});
Doesn't seem that the other jsfiddle example works anymore.
For others who want to get the right libraries set up to see this working, see:
http://jsfiddle.net/kp8a8ugd/1/
var swiper = new Swiper('.swiper-container'); //just a simple setup
const swiper = new Swiper('.swiper', {
// Optional parameters
direction: 'vertical',
loop: true,
// If we need pagination
pagination: {
el: '.swiper-pagination',
},
// Navigation arrows
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
// And if we need scrollbar
scrollbar: {
el: '.swiper-scrollbar',
},
});