Vue.js and replacement for data-portal-component attribute


I’ve integrated Vue.js to my enonic CMS, and because of that im having a harder time using thymeleaf attributes because of how vue injects content to the body.

What I need is to be able to get each part inside a region and manually insert them to the region because the data-portal-component attribute does not work for me either. Is there a way to replace this functionality in javascript? What tools do i use?

If there is a way i can use the data-portal-component with Vue.js id be happy to learn how!

Enonic version: 7.3.0
OS: Win32

Hello, Eirik!

It can certainly be done, but I don’t know if someone has done it before like what’s been done with the React4XP library and starter, or if you need to implement this yourself.

You mention that Vue makes it difficult to use the data-portal-component attribute because of “how Vue injects content into the body”. To that I will add that it’s not so much how Vue injects content, but rather when Vue injects content.

Image shamelessly copied from the Enonic XP site engine documentation:

The data-portal-component is the link between the “Page renderer” bubble and the “Component Renderer” bubble. But all this is happening server-side before the HTML document is delivered to the browser, while Vue.js is running client-side, i.e. after the Common pipeline in the end of the diagram above. So you have three options:

  1. Skip the whole Component Renderer step, and instead just have a simple Page Renderer and then write your own component renderer from scratch that extracts data from Enonic XP and will do the rest of the rendering client-side. I foresee relatively quick results if you go this route, but also lots of things that will no longer work, such as all the portal URL’s, macros, and not to forget the live edit mode inside Content Studio where you can drag and edit layouts, parts, and other components onto a page. All of that will no longer work. Therefore, I really don’t recommend this at all!
  2. Make Vue.js (either partly or fully) work server-side, so that it can process data from XP and render it into HTML before passing it further down the pipeline. This is by far the most elegant solution, but it does require a bit of work if nobody else has done it before you. Many Vue projects rely on Node.js which does have its subtle but important differences compared to what’s supported in the server-side Nashorn JavaScript engine that Enonic XP 7 is running, and you need to find workarounds for those differences.
  3. Dual and redundant logic, both server-side and client-side. The server-side logic would render your pages and components using regular Enonic XP methodology, but only as a static markup that looks just like your Vue app when the page is loaded in the browser. The client-side logic would then replace this initial static placeholder markup with the actual Vue application, similar to how the Vue app typically replaces everything inside the <div id="app"></div> container. This should not be that difficult for you to implement quickly, but is harder to maintain because it’s very specific to your app and you need to do a lot of the same things twice because server-side and client-side JS can’t access the same data model.

If you have the time, I would recommend looking into how React4XP has solved the same predicament for those who want to integrate React apps into the Enonic XP site engine pipeline, following option #2 above. React4XP lets you run React code server-side, essentially letting you write code for parts using React as if it were regular JavaScript.

So if nobody else in this forum has any experience with integrating Vue with enonic that they can share here, I would recommend first trying a simple hard-coded proof of concept of option #3, and then either continue along that route or if you feel inspired: go for the more elegant option #2 similar to what has been done with React4XP.

I hope these answers have been useful, even though I don’t have experience with Vue myself.


Hi! A bit more info on your use case would be helpful. Are you looking to render Everything frontend using Vue? A more specific example would help.