Sentry Answers>Vue.js>

How do I use custom elements with Vue.js?

How do I use custom elements with Vue.js?

Richard C.

The Problem

Custom elements are part of the Web Components specification in modern HTML. They are lowercase HTML elements including a dash, such as <person-details>. This element is custom JS and HTML you write, that behaves in the same way as standard HTML elements like <div> and <span>.

Since custom element names look similar to components you create in React, Vue.js, or other web frameworks, the frameworks might be confused when encountering them.

You might get an error message like the following:

Click to Copy
Failed to resolve component: component-name If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.

You might see this error when you are working with a Laravel project that is using Vue.js as its browser framework. Vue.js is the underlying cause of the error.

The Vue.js documentation says:

By default, Vue will attempt to resolve a non-native HTML tag as a registered Vue component before falling back to rendering it as a custom element. This will cause Vue to emit a failed to resolve component warning during development. To let Vue know that certain elements should be treated as custom elements and skip component resolution, we can specify the compilerOptions.isCustomElement option.

Custom elements are compatible with Vue, but you need to tell your project you’re using one.

The Solution

The most common cause for the Unknown custom element error is not a configuration problem, but rather that you misspelled the tag. For example, instead of <person-details>, you may have written <persan-details>. Check your spelling before trying the other solutions below.

Removing the error message will differ depending on whether you are using Vue 2 or Vue 3.

Vue 2

Vue 2 was deprecated in 2023, but you might need to maintain an old project that has not yet upgraded to Vue 3.

Vue 2 documentation says you need to use Vue.config.ignoredElements in your code or custom elements will cause an error.

For example:

Click to Copy
Vue.config.ignoredElements = ['person-details']; const app = new Vue({ el: '#app', data: { message: 'Hello Vue!'} });

For a full working example, try the following index.html file:

Click to Copy
<html lang="en"> <head> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <!-- Create a web component --> <script> class PersonDetails extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); this.shadowRoot.innerHTML = `<p>Person Record Component</p>`; } } customElements.define("person-details", PersonDetails); </script> <div id="app"> {{ message }} <person-details></person-details> </div> <script> Vue.config.ignoredElements = ["person-details"]; var app = new Vue({ el: "#app", data: { message: "Hello Vue!", }, }); </script> </body> </html>

Vue 3

In Vue 3, the method to remove the error message will differ depending on whether you are creating Vue components at runtime or using a build step.

Creating Components at Runtime

If you are creating a Vue application at runtime without a build step, you will have code to initialize your app similar to the following:

Click to Copy
const { createApp } = Vue; const app = createApp({ data() { return { message: 'Hello Vue!' } } });

Below this, add the following configuration line:

Click to Copy
app.config.compilerOptions.isCustomElement = (tag) => ['person-details', 'another-element'].includes(tag);

If you refresh the page, you should no longer get an error message.

For a full working example, try the following index.html file:

Click to Copy
<html lang="en"> <head> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body> <!-- Create a web component --> <script> class PersonDetails extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); this.shadowRoot.innerHTML = `<p>Person Record Component</p>`; } } customElements.define("person-details", PersonDetails); </script> <div id="app"> {{ message }} <person-details></person-details> </div> <script> const { createApp } = Vue; const app = createApp({ data() { return { message: "Hello Vue!" }; }, }); app.config.compilerOptions.isCustomElement = (tag) => ["person-details", "another-element"].includes(tag); app.mount("#app"); </script> </body> </html>

Creating Components With a Build Step

If you are using a JavaScript bundler, like Parcel, webpack, Browserify, or Vite — or working with TypeScript using tsc or Babel — you need to configure custom elements in your build step. (You might get rid of the error using only the app.config.compilerOptions.isCustomElement line from the previous section, so try that first, but otherwise use the code in this section.)

For Vite, in the vite.config.js file, you can use the template’s compilerOptions object to set a function defining what a custom element name is. For example:

Click to Copy
import vue from '@vitejs/plugin-vue' export default { plugins: [ vue({ template: { compilerOptions: { isCustomElement: (tag) => ['person-details', 'another-element'].includes(tag) } } }) ] }

If you’re using webpack, add a rule like the following to webpack.config.js:

Click to Copy
rules: [ { test: /\.vue$/, use: 'vue-loader', options: { compilerOptions: { isCustomElement: tag => ['person-details', 'another-element'].includes(tag) } } } ]

If you’re using Parcel or the old Vue CLI, add the isCustomElement line to your vue.config.js file.

Further Reading

If you still have trouble with custom elements in Vue, read the full documentation:

  • Syntax.fm logo
    Listen to the Syntax Podcast

    Tasty treats for web developers brought to you by Sentry. Get tips and tricks from Wes Bos and Scott Tolinski.

    SEE EPISODES

Considered “not bad” by 4 million developers and more than 100,000 organizations worldwide, Sentry provides code-level observability to many of the world’s best-known companies like Disney, Peloton, Cloudflare, Eventbrite, Slack, Supercell, and Rockstar Games. Each month we process billions of exceptions from the most popular products on the internet.

© 2024 • Sentry is a registered Trademark of Functional Software, Inc.