Skip to content

Vue 3 Integration

import { Aside } from ‘@astrojs/starlight/components’;

Because <spartan-login> is a native web component, it is not integrated with Vue’s reactivity system. You need to use Vue’s lifecycle hooks to wire up event listeners and handle attribute changes.

src/views/LoginView.vue
<template>
<spartan-login
:key="widgetKey"
ref="loginWidget"
:domain="authDomain"
:sector="sectorId"
start-mode="password"
:locale="locale"
redirect="">
</spartan-login>
</template>
<script setup lang="ts">
import '@masonitestudios/spartanauth-widgets';
import { ref, watch, onBeforeUnmount } from 'vue';
import { useRouter } from 'vue-router';
const router = useRouter();
const authDomain = import.meta.env.VITE_SPARTANAUTH_DOMAIN || 'https://api.spartanauth.com';
const sectorId = import.meta.env.VITE_SPARTANAUTH_SECTOR;
const locale = ref(navigator.language.slice(0, 2) || 'en');
const widgetKey = ref(0);
const loginWidget = ref<HTMLElement | null>(null);
function onLogin() {
router.push('/');
}
// Attach/detach the listener whenever the widget mounts or remounts.
// Using watch on the ref handles both initial mount and remounts caused by key changes.
watch(loginWidget, (newEl, oldEl) => {
oldEl?.removeEventListener('spartan-login', onLogin);
newEl?.addEventListener('spartan-login', onLogin);
});
// Belt-and-suspenders cleanup on route leave
onBeforeUnmount(() => {
loginWidget.value?.removeEventListener('spartan-login', onLogin);
});
// Force a remount when locale changes so the widget re-reads the attribute
watch(locale, () => { widgetKey.value++; });
</script>

The web component element does not exist in the DOM before the component mounts. Use watch(ref, ...) — not onMounted alone — because the ref watch also fires on remounts (see below).

Always pair your addEventListener with a removeEventListener in onBeforeUnmount or in the watch cleanup. Otherwise event listeners accumulate and leak.

3. Use :key to force remount on attribute changes

Section titled “3. Use :key to force remount on attribute changes”

Vue reuses DOM nodes when possible. When the locale attribute (or any attribute that the widget reads on initialization) changes, the widget needs to be destroyed and recreated to pick up the new value.

Incrementing :key forces Vue to replace the element entirely:

// Force remount when locale changes
watch(locale, () => { widgetKey.value++; });

Without this, setting a new locale attribute will not take effect because the widget reads its i18n configuration once at creation time.

4. Tell Vue to treat spartan-* as custom elements

Section titled “4. Tell Vue to treat spartan-* as custom elements”

If you see Vue warnings about unknown elements, configure vite.config.ts:

vite.config.ts
import vue from '@vitejs/plugin-vue';
export default {
plugins: [
vue({
template: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('spartan-'),
},
},
}),
],
};
MistakeFix
Attaching the listener in onMounted instead of watch(ref, ...)watch handles remounts; onMounted only runs once
Forgetting onBeforeUnmount cleanupAlways pair addEventListener with removeEventListener
Not incrementing :key when locale changeswatch(locale, () => { widgetKey.value++ })
Using v-model or reactive bindings on widget attributesWeb components don’t observe attribute changes reactively — use :key remount instead