Ionic 6 + Svelte 🚀

Raymond Boswel
3 min readDec 25, 2021

--

As a long time user of Ionic, and an avid user of Svelte, I was quite excited with the release of Ionic 6. In Ionic 6, the Ionic team added a Custom Elements build, which allows Ionic to be used with bundlers such as Vite and Rollup. In this article I will go over the steps to get up and running with Svelte and Ionic.

Installation

If you’re starting from scratch, it’s often a good idea to get off to a running start. Since we’re focusing on Ionic, it’s quite likely that at some point you want to compile your application to native apps. So perhaps take a look at https://github.com/drannex42/svelte-capacitor as a starting point.

Once you have a running app you can go ahead and install Ionic:

npm i @ionic/core

Setup

To use the components in your application, you need to add the following to your root component:

// App.Svelte
import { initialize } from "@ionic/core/components";
// Add imports for all components used in your application
// Note: The componets MUST be imported from @ionic/core/components
import { IonApp } from "@ionic/core/components/ion-app";
import { IonButton } from "@ionic/core/components/ion-button";
import { defineCustomElement as defineLoading } from "@ionic/core/components/ion-loading";
import { defineCustomElement as defineAlert } from "@ionic/core/components/ion-alert";
import { defineCustomElement as defineToast } from "@ionic/core/components/ion-toast";
import {
defineCustomElement as defineActionSheet,
} from "@ionic/core/components/ion-action-sheet";
onMount(() => {
initialize();
// Overlay components need some special handling
defineActionSheet();
defineModal();
defineLoading();
defineAlert();
defineToast();
// The rest of the ion-elements can be defined as below
tryDefine("ion-app", IonApp);
tryDefine("ion-input", IonInput);
tryDefine("ion-button", IonButton);
// Repeat for all components used in your application
}// Prevents exception when hot reloading.
function tryDefine(tag, impl) {
try {
customElements.define(tag, impl);
} catch (error) {}
}
// Applies required global styles
document.documentElement.classList.add("ion-ce");
});

Usage

Once the components have been initialized in the root component you can use the Ionic components in your svelte files. There are however some parts of Ionic which need special attention. This includes modals, popovers and Ionicons.

Modals

There are two approaches available to make use of Ionic’s modals. You can either make use of the modalController, or add an <ion-modal> element to your template. In order to use the modalController, the following function helps take care of the details:

import {
modalController
} from "@ionic/core";
export const IonicShowModal = async (
selector: string,
component: new (...args: any) => SvelteComponent,
componentProps: any
) => {
const modal = await modalController.create({
component: selector,
componentProps,
});
await modal.present();
// Ensure only one element is returned here.
let elem = document.getElementsByTagName(selector)[0];
let svelteComponent = new component({ target: elem, props: componentProps });let res = await modal.onWillDismiss();svelteComponent.$destroy();
elem.remove();
return res;
};
// Usageimport CreateProject from "@components/CreateProject.svelte";
IonicShowModal("wc-create-project", CreateProject, {});

Alternatively, you can add an ion-modal tag in your template, which needs to have the ‘ion-page’ class applied to properly fit the content to the screen:

<ion-modal class="ion-page" bind:this={modal} is-open={showModal}>
<CreateProject />
</ion-modal>

These two approaches have somewhat different ergonomics, but boil down to the same output, so it really comes down to your preference. Coming from ionic/angular, the modalController based approach feels more familiar to me.

Popovers

You can use the controller based approach with popovers as well.

Ionicons

Update: As with the rest of the framework you just have to know how to reference the icons correctly, and not use the lazy loading facility which isn’t compatible with bundlers such as Vite. A quick example follows:

<script>
import { airplane } from "ionicons/icons";
import { actionSheetController } from "@ionic/core/components";
function showActionSheet() {
const actionSheet = actionSheetController.create({
buttons: [{
text: "Yay",
icon: airplane
}]
});
}
</script>
<div>
<ion-icon on:click={showActionSheet} icon={airplane} ></ion-icon>

Wrap up

This pretty much covers all the little details I had to take care of when adding Ionic to one of my projects. Please let me know if I missed anything, or if there’s anything that doesn’t work as expected. And thanks to the Ionic team for creating such an amazing ecosystem and being so responsive to my support requests!

--

--