telion
telion

Reputation: 1120

How do I use PrimeVue in CustomElements?

I have a Vue 3 custom Element in which I want to use PrimeVue & PrimeFlex etc. So I first create a Component, use the .ce.vue extension for the sfc mode and use the combination of defineCustomElement and customElements.define to compile it to a web component. Finally I use it in the index.html to see if it works in the Browser.

It works to some extent but not completely. For example, I am unsure about how to translate app.use(PrimeVue) for my case.

//customElement.ce.vue
<template>
  <div>Test</div>
  <AutoComplete field="name" />
</template>

<script lang="ts">
import { defineComponent } from "vue";
import AutoComplete from "primevue/autocomplete";

export default defineComponent({
  name: "customElement",
  props: {
    msg: String,
  },
  components: { AutoComplete },
  setup: () => {
    console.log(JSON.stringify(theme));
    return { PrimeVue };
  },
  styles: [],
});
</script>
<style scoped lang="scss"></style>
//main.ts
import { createApp, defineCustomElement } from "vue";
import App from "./App.vue";

//PrimeVue
import PrimeVue from "primevue/config";
import "/node_modules/primeflex/primeflex.css";
import "primevue/resources/primevue.min.css";
import "primevue/resources/themes/saga-blue/theme.css";

//CustomElement
import customElement from "@/components/customElement.ce.vue";

const customElementWC = defineCustomElement(customElement);
customElements.define("custom-element", customElementWC);

//Setup VueApplication for testing/reference, this works as expected. 
const app = createApp(App);
app.use(PrimeVue);
app.mount("#app");
//index.html (for testing) 
<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <noscript>
      <strong
        >We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
        properly without JavaScript enabled. Please enable it to
        continue.</strong
      >
    </noscript>
    <div id="app"></div>    //test app
    <custom-element />      //the custom Web Component
    <!-- built files will be auto injected -->
  </body>
</html>

So I can see that the PrimeVue-Autocomplete is being shown, but the styles are not working.

So the question is:

How can I use all of PrimeVue in a custom Component?

Or in other words: How do I setup a Vue 3 CustomElement with PrimeVue?

Upvotes: 3

Views: 2571

Answers (1)

telion
telion

Reputation: 1120

So I have found a workaround (not a proper solution). The way to make most of it work is to import the styles and js/ts modules in the component(s) itself.

The main styles make the most sense to import in the root component of the web component. The reason why it has to be there is, due to:

I still couldn't properly import primeflex so I had to use the cdn link. I think it is possible to use an internal import, and I will update the answer when I find out how.

To use a specific PrimeVue component, simply import and register it as the documentation describes.

<template>
 <Button />
</template>

<script lang="ts">
import Button from "primevue/button";
import { defineComponent } from "vue";
export default defineComponent({
 components: { Button },
});
</script>

<style>
@import url("https://unpkg.com/[email protected]/primeflex.css");
</style>
<style lang="scss" src="@/assets/scss/globals.scss"></style>
<style src="primevue/resources/primevue.min.css"></style>
<style src="primevue/resources/themes/tailwind-light/theme.css"></style>

//main.ts
import { defineCustomElement } from "vue";
import App from "./App.ce.vue";

customElements.define("custom-element", defineCustomElement(App));

Limitation: Due to the missing plugin support (or my lack of knowledge of it) the lines:

import PrimeVue from 'primevue/config';
app.use(PrimeVue);

are not possible. Unfortunately, I can't fully grasp the impact that might have.

Upvotes: 0

Related Questions