Ionic Framework VueJS and SwiperJS
Ionic has depreciated IonSlides in the v6 release and recommends using the underlying library SwiperJS.
In this short post I show how to integrate SwiperJS and it VueJS wrapper to display a set of slides holding IonCards. How to dynamically add and removed slides from the list of slides using the SwiperJS library.
See Previous Video For Setting Up Vite & Ionic Project
Also because vitejs is awesome and fast, I will be using that as the starting point for my application. See more information on Ionic and ViteJS and how to setup the app in the video I posted last week.
Video Version of Blog Post
Adding SwiperJS
after the project is set up you need to add SwiperJS to the project
npm i swiper
Also we will be adding some styling from the swiper library so to avoid the sass
errors, we need to install another library
npm install -D sass
Creating Slides Page
This is the template section for the component, most of this is basic ionic setup
<template>
<ion-page>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title>Ionic Vite - Swiper - Slides</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
// will add slides content here...
</ion-content>
</ion-page>
</template>
Next we need to include the appropriate imports
<script lang="ts">
import { defineComponent, ref } from "vue";
import {
IonContent,
IonButton,
IonButtons,
IonBackButton,
IonPage,
IonHeader,
IonTitle,
IonToolbar,
IonModal,
IonCard,
IonCardContent,
} from "@ionic/vue";
// Import Swiper Vue.js components
import { Swiper, SwiperSlide } from "swiper/vue";
// Import Swiper styles
import "swiper/swiper.scss";
export default defineComponent({
name: "Slides",
components: {
IonHeader,
IonPage,
IonButton,
IonButtons,
IonBackButton,
IonContent,
IonTitle,
IonToolbar,
IonCard,
IonCardContent,
Swiper,
SwiperSlide,
},
setup() {
return {
};
},
});
</script>
There are some styles that i figured out to make the page look ok, you can play around with them in your example. The .swiper-slide
and .swiper-container
are classes from the SwiperJS
documentation
<style>
ion-card {
height: 90%;
}
.swiper-slide {
padding: 12px;
text-align: center;
font-size: 28px;
background: #fff;
}
.swiper-container {
width: 100%;
height: 80%;
}
</style>
Lets create a data structure, slideData
to hold our slide content and be sure to return it so it can be accessed in the template
setup() {
// data used to draw slides
const slideData = ref<any>([{ id: "1" }]);
return {
slideData,
};
},
Dynamically Adding Slides To Page
Lets add our slide components to the template, we will loop through the slideData
to render a slide for each entry in the slideData
<template>
<ion-page>
<ion-header>
<ion-toolbar>
<ion-title>Ionic Vite - Swiper - Slides</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<!-- header on page -->
<div style="padding-left: 10px">
<h1>Swiperjs Slides</h1>
</div>
<!-- slides created by loopong through slideData -->
<swiper :pagination="{ clickable: true }" >
<template v-for="s in slideData" :key="s.id">
<swiper-slide>
<!-- put IonCard inside of the swiper-slide element -->
<ion-card>
<ion-card-content>
<!-- using name from data for slide title -->
<div>Slide Name {{ s.name }}</div>
</ion-card-content>
</ion-card>
</swiper-slide>
</template>
</swiper>
</ion-content>
</ion-page>
</template>
One last step is making sure that the swiper library knows that we have updated the DOM by adding slides. The documentation states that when adding slides through javascript, you should call swiper.update()
we will do that in the onMounted
lifecycle event.
onMounted(() => {
setTimeout(() => {
swiperRef.value.update();
}, 1);
});
Now to add more slides to the page, we just need to add more data to the slideData
object and since it is a ref, and observable, when it changes the template will be re-rendered with the new content.
Add a new function in setup
and return the function so it can be accessed in the template
setup() {
// data used to draw slides
const slideData = ref<any>([{ id: "1", name: "initial slide" }]);
// adds a slide to the list by updating the data that
// the slides are derived from
const addSlide = () => {
slideData.value = [
{ id: new Date().getTime() + "", name: new Date() + "" },
...slideData.value,
];
};
return {
slideData,
addSlide,
};
},
Add a new button in the templated
<template>
<ion-page>
<ion-header>
<ion-toolbar>
<ion-title>Ionic Vite - Swiper - Slides</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<!-- header on page -->
<div style="padding-left: 10px">
<h1>Swiperjs Slides</h1>
</div>
<!-- slides created by loopong through slideData -->
<swiper :pagination="{ clickable: true }">
<template v-for="s in slideData" :key="s.id">
<swiper-slide>
<!-- put IonCard inside of the swiper-slide element -->
<ion-card>
<ion-card-content>
<!-- using name from data for slide title -->
<div>Slide Name {{ s.name }}</div>
</ion-card-content>
</ion-card>
</swiper-slide>
</template>
</swiper>
<!--------------------------------->
<!-- new button for adding slide -->
**<div style="padding-left: 10px">
<ion-button @click="addSlide">ADD SLIDE</ion-button>
</div>**
</ion-content>
</ion-page>
</template>
Getting The Swiper Instance
The SwiperJS Vue Component has an event that will provide us with the swiper instance as soon as it is available. Lets change the template and the setup
function to get the instance
@swiper="onSwiperInstance"
listener added to get swiper instance
<!-- slides created by loopong through slideData -->
<!-- @swiper="onSwiperInstance" listener added to get swiper instance -->
<swiper :pagination="{ clickable: true }" **@swiper="onSwiperInstance"**>
<template v-for="s in slideData" :key="s.id">
<swiper-slide>
<!-- put IonCard inside of the swiper-slide element -->
<ion-card>
<ion-card-content>
<!-- using name from data for slide title -->
<div>Slide Name {{ s.name }}</div>
</ion-card-content>
</ion-card>
</swiper-slide>
</template>
</swiper>
need to change setup
to include the function onSwiperInstance
and return it so the template can access it
setup() {
// data used to draw slides
const slideData = ref<any>([{ id: "1", name: "initial slide" }]);
**// NEW ->
// reference to swiper
const swiperRef = ref<any>(null);**
onMounted(() => {
setTimeout(() => {
swiperRef.value.update();
}, 1);
});
**// NEW ->
// used to get an instance of the swiper object after it is
// initialized
const onSwiperInstance = (v: any) => {
console.log("onSwiperInstance", v);
swiperRef.value = v;
};**
// adds a slide to the list by updating the data that
// the slides are derived from
const addSlide = () => {
slideData.value = [
{ id: new Date().getTime() + "", name: new Date() + "" },
...slideData.value,
];
};
return {
slideData,
addSlide,
**onSwiperInstance**
};
},
If you look in the console, you will see that we now have the swiper instance to be utilized to call any of the functions available to you from the SwiperJS API
Removing Slides from Page
We remove slides the same way we add slides, by updating the slideData
property of the component.
Lets add a delete button to the slide, the button will call a function removeSlide
and as a parameter, pass in the id
of the slide to remove.
<swiper :pagination="{ clickable: true }" **@swiper="onSwiperInstance"**>
<template v-for="s in slideData" :key="s.id">
<swiper-slide>
<!-- put IonCard inside of the swiper-slide element -->
<ion-card>
<ion-card-content>
<!-- using name from data for slide title -->
<div>Slide Name {{ s.name }}</div>
<ion-button @click="removeSlide(s.id)">DELETE SLIDE</ion-button>
</ion-card-content>
</ion-card>
</swiper-slide>
</template>
</swiper>
Lets update to setup
to include the removeSlide
function
setup() {
// data used to draw slides
const slideData = ref<any>([{ id: "1", name: "initial slide" }]);
// reference to swiper
const swiperRef = ref<any>(null);
onMounted(() => {
setTimeout(() => {
swiperRef.value.update();
}, 1);
});
// used to get an instance of the swiper object after it is
// initialized
const onSwiperInstance = (v: any) => {
console.log("onSwiperInstance", v);
swiperRef.value = v;
};
// adds a slide to the list by updating the data that
// the slides are derived from
const addSlide = () => {
slideData.value = [
{ id: new Date().getTime() + "", name: new Date() + "" },
...slideData.value,
];
};
// remove a slide from the list by filtering the data that
// the slides are derived from
const removeSlide = (slideId: any) => {
let newData = slideData.value.filter((s: any) => s.id !== slideId);
slideData.value = newData;
};
return {
slideData,
addSlide,
onSwiperInstance,
removeSlide
};
},
FULL SOURCE CODE
<template>
<ion-page>
<ion-header>
<ion-toolbar>
<ion-title>Ionic Vite - Swiper - Slides</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<div style="padding-left: 10px">
<h1>Swiperjs Slides</h1>
</div>
<swiper :pagination="{ clickable: true }" @swiper="onSwiperInstance">
<template v-for="s in slideData" :key="s.id">
<swiper-slide>
<ion-card>
<ion-card-content>
<div>Slide {{ s.id }}</div>
<ion-button @click="removeSlide(s.id)">DELETE SLIDE</ion-button>
</ion-card-content>
</ion-card>
</swiper-slide>
</template>
</swiper>
<div style="padding-left: 10px">
<ion-button @click="addSlide">ADD SLIDE</ion-button>
</div>
</ion-content>
</ion-page>
</template>
<script lang="ts">
import { defineComponent, ref } from "vue";
import {
IonContent,
IonButton,
IonPage,
IonHeader,
IonTitle,
IonToolbar,
IonCard,
IonCardContent,
} from "@ionic/vue";
import SwiperCore, { Navigation, Pagination, Scrollbar, A11y } from "swiper";
// Import Swiper Vue.js components
import { Swiper, SwiperSlide } from "swiper/vue";
// Import Swiper styles
import "swiper/swiper.scss";
import "swiper/components/navigation/navigation.scss";
import "swiper/components/pagination/pagination.scss";
import "swiper/components/scrollbar/scrollbar.scss";
export default defineComponent({
name: "Slides",
components: {
IonHeader,
IonPage,
IonButton,
IonContent,
IonTitle,
IonToolbar,
IonCard,
IonCardContent,
Swiper,
SwiperSlide,
},
setup() {
// reference to swiper
const swiperRef = ref<any>(null);
// data used to draw slides
const slideData = ref<any>([{ id: "1" }]);
onMounted(() => {
setTimeout(() => {
swiperRef.value.update();
}, 1);
});
// used to get an instance of the swiper object after it is
// initialized
const onSwiperInstance = (v: any) => {
console.log("onSwiperInstance", v);
swiperRef.value = v;
};
// adds a slide to the list by updating the data that
// the slides are derived from
const addSlide = () => {
slideData.value = [{ id: new Date().getTime() + "" }, ...slideData.value];
};
// remove a slide from the list by filtering the data that
// the slides are derived from
const removeSlide = (slideId: any) => {
let newData = slideData.value.filter((s: any) => s.id !== slideId);
slideData.value = newData;
};
return {
slideData,
onSwiperInstance,
addSlide,
removeSlide,
};
},
});
</script>
<style>
ion-card {
height: 90%;
}
.swiper-slide {
padding: 12px;
text-align: center;
font-size: 28px;
background: #fff;
}
.swiper-container {
width: 100%;
height: 80%;
}
</style>
Github Project
aaronksaunders / vite-ionic-slides-project
ionic v6 beta vitejs slides implemented using swiperjs
Getting Started with ViteJS, Ionic Framework Beta v6 SwiperJS And VueJS
This template should help get you started developing with Ionic, Vue 3 and Typescript in Vite.
Ionic has depreciated IonSlides in the v6 release and recommends using the underlying library SwiperJS.
In this short post I show how to integrate SwiperJS and it VueJS wrapper to display a set of slides holding IonCards. How to dynamically add and removed slides from the list of slides using the SwiperJS library.
Recommended IDE Setup
VSCode + Vetur. Make sure to enable vetur.experimental.templateInterpolationService
in settings!
If Using <script setup>
<script setup>
is a feature that is currently in RFC stage. To get proper IDE support for the syntax, use Volar instead of Vetur (and disable Vetur).
Type Support For .vue
Imports in TS
Since TypeScript cannot handle type information for .vue
imports, they are shimmed to be a generic Vue…
Top comments (0)