I am trying to create a widget with Vue3, which can be integrated with isolated styles in other websites. I am trying to create it as a custom element. I am using PrimeVue as the component framework. While compiling locally, my test project is rendered correctly. However, when I build it and host the generated js file on a server and embed it in a website, the DOM is loaded incorrectly (InputText-Component isn't displayed. The button, however, does correctly) and I get an error in the console:
TypeError: Cannot read properties of undefined (reading 'config')
in the builded/loaded js-file, in line:
"p-variant-filled": e.variant ? e.variant === "filled" : r.$primevue.config.inputStyle === "filled"
- "primeflex": "^3.3.1",
- "primeicons": "^6.0.1",
- "primevue": "^3.49.1",
- "vue": "^3.4.15"
My Vue projectfiles
App.ce.vue
<script>
import Button from "primevue/button";
import FloatLabel from "primevue/floatlabel";
import InputText from 'primevue/inputtext';
export default {
name: 'App',
components: {
Button, FloatLabel, InputText
},
}
</script>
<template>
<header>
</header>
<main>
<FloatLabel>
<InputText id="username" />
<label for="username">Username</label>
</FloatLabel>
<Button label="Submit" />
</main>
</template>
<style>
@import 'primevue/resources/themes/lara-light-green/theme.css';
@import 'primevue/resources/primevue.min.css';
@import 'primeflex/primeflex.css';
@import 'primeicons/primeicons.css';
</style>
widget-entry.js
import {defineCustomElement} from 'vue';
import App from "./App.ce.vue";
const WidgetElement = defineCustomElement(App);
customElements.define('my-widget', WidgetElement);
main.js
import 'primevue/resources/themes/lara-light-green/theme.css'
import 'primevue/resources/primevue.min.css';
import 'primeflex/primeflex.css';
import 'primeicons/primeicons.css'
import { createApp } from 'vue'
import App from './App.ce.vue'
import PrimeVue from 'primevue/config';
import FloatLabel from 'primevue/floatlabel';
import InputText from 'primevue/inputtext';
import Button from "primevue/button";
const app = createApp(App);
app.use(PrimeVue);
app.component('FloatLabel', FloatLabel);
app.component('Button', Button);
app.component('InputText', InputText);
app.mount('#app')
vite-config
import {fileURLToPath, URL} from 'node:url'
import {defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default ({mode}) => {
const env = loadEnv(mode, process.cwd(), "");
return defineConfig({
define: {
"process.env": env,
},
plugins: [
vue()
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
//Begin configuration, to compile into one single file
build: {
lib: {
entry: 'src/widget-entry.js',
name: 'MyWidget',
fileName: (format) => format === 'umd' ? 'registration-widget.js' : `registration-widget.${format}.js`
}
}
})
}
Embedding into my webpage with
<script src="https://path/to/my/js/file"></script>
<div style="height: 500px; width: auto; overflow-y: auto;">
<my-widget></my-widget>
</div>