Try our conversational search powered by Generative AI!

John-Philip Johansson
Oct 31, 2018
(10 votes)

Tips and tricks for a great On-Page Editing experience in SPAs and other client side rendered sites

To get access to the new features explained in this blog post, you will need to enable beta features. This is done by following the following documentation. Beta features

To demonstrate some concepts useful when creating a SPA with working OPE, we are releasing a new SPA template site on Github, called MusicFestival, together with a series of blog posts. Don't be discouraged that the SPA is written in Vue.js if you're using React, Angular, or something else, as these concepts will work in any client side framework.

Introducing a new SPA template site: MusicFestival

When creating a SPA, you are no longer bound by certain limitations on a server side rendered site, but it's important to remember that the site still lives in a Content Management System (CMS) and that there is a human editor whose job it is to edit the site. These editors learn the concepts in the CMS user interface and feel happier when they are able to feel productive. By following these tips and tricks, you can allow your editors to have a nice editing experience, while keeping all the productive niceness of writing a site by focusing mostly on the frontend without having to focus too much on what CMS is being used behind the API.

A more in-depth look at what you need to think about when doing client side routing is available in this blog: Routing in a SPA with a working On-Page Editing experience (CMS UI 11.11.0).

This blog will instead focus on examples on what you can do with your site to improve the editors On-Page Editing (OPE) experience.

In CMS UI 11.11.0, we introduce some useful properties on the injected epi.beta property. In the template, we make them available to all components as $epi, which is a Vue.js instance property. You'll see it used throughout the examples.

Routing links vs edit links

As is mentioned in the routing blog, you will want to render different HTML depending on if you're in edit mode or view mode. To simplify this, we created a Link component that does this.

    <!-- Editmode -->
    <a v-if="$epi.inEditMode" :href="url">

    <!-- Viewmode -->
    <router-link v-else :to="url">

<slot> allows child components to be passed by the parent component. See Vue.js docs

See the full source for the EpiLink.vue component [here](

Disabling links in OPE

Certain links, such as a language selector in MusicFestival, are disabled when in OPE, because when switching languages it is more appropriate to use the CMS UI. There can be other use cases, so we created a ViewModeLink component. We do not change the HTML in OPE as to not affect the styling, and instead simply disable the pointer events so they aren't interactive or clickable.

Disabling links in OPE

    <router-link :class="{ 'edit-mode': $epi.inEditMode }" :to="url">

<style lang="less" scoped>
    .edit-mode {
        pointer-events: none;

See the full source for the EpiViewModeLink.vue component here.

Editing a visible property

To make an element editable in OPE, you can add certain attributes to the HTML, such as <span data-epi-property-name="Name">. Information regarding those attributes can be found in our Developer guides.

As with @Html.EditAttributes(), available in ASP.NET Razor views, these attributes should not be rendered for the site visitor in view or preview modes.

To make this more convenient, we created a custom Vue.js directive (an element property) called v-epi-edit that will add all required attributes to any element using that directive. It's also possible for a component to disable the editing features by having the property epiDisableEditing set to false. We will show a useful scenario in the section "Hiding overlays when they interfere with new overlays due to user interactions".

Edit visible property

Using it is straightforward:

<!-- This Vue.js code: -->
<h1 v-epi-edit="'ArtistName'">{{model.artistName}}</h1>

<!-- Becomes ths HTML code: -->
<h1 data-epi-property-name="ArtistName" data-epi-property-render="none" data-epi-property-edittype="floating">...</h1>

Its implementation is quite simple too:

function toggleEditAttributes(el, binding, vnode) {
    const siteIsEditable = vnode.context.$epi.isEditable;
    const componentIsEditable = !vnode.context.epiDisableEditing;

    if (siteIsEditable && componentIsEditable) {
        setEditAttributes(el, binding);
    } else {

You can see the implementation in epiEdit.js.

Editing a non-visible or hard to click property

Edit non-visible property

We also created the EpiProperty component to have a way to edit properties that might be hard to edit using the normal editing overlays, such as the background image of the ArtistDetailsPage component. It renders a <button> when the page is editable.

These elements should not be rendered for the site visitor, in view or preview modes.

    <button v-if="$epi.isEditable" v-epi-edit="propertyName">Edit property: {{propertyName}}</button>

Note that it uses the EpiEdit directive to be editable.

See the full source for the EpiProperty.vue component here.

Hiding overlays when they interfere with new overlays due to user interactions

There are situations when one editable property is rendered on top of another. In the MusicFestival site, this happens when the BuyTicketBlock modal is shown on top of the Hero image on the LandingPage. To help the editor, the Hero's editable properties have their editing features disabled in those cases, so the overlays don't fight for the user's attention.

Hiding selected overlays

If you recall the v-epi-edit directive (the custom attribute) introduced in the section "Editing a visible property", it allows the element it's on to disable editing by setting the property epiDisableEditing to true. You can see it used indirectly on the Title in the Hero component:

    <h1 v-epi-edit="'Title'" v-html="title"></h1>

export default {
    computed: {
        epiDisableEditing() {
            return this.$app.modalShowing;

See the full source for the Hero.vue component here.

The v-epi-edit directive will read the epiDisableEditing value set by Hero and disable the overlays when the site's modal is showing.

Set minimum size for editing overlays

Since CMS UI 11.11.0, there is a CSS injected to set the min-size so that properties with empty values can still be edited in OPE mode. This is otherwise set on the server side rendered HTML when not using data-epi-property-render="none".

Setting minimum size on empty overlay

You can set your own minimum size by overriding the selector [data-epi-property-name]. The injected CSS is:

[data-epi-property-name] {
    min-height: 14px;
    min-width: 18px;

Related links

Template site using the techniques discussed in this blog:

Documentation on client side rendering in Episerver:

Oct 31, 2018


Please login to comment.
Latest blogs
Introducing Image Transformer - AI Assistant for Optimizely

We've got something super cool to share with you, and it's all about giving your images a fresh spin. Image Transformer, the latest feature from ou...

Luc Gosso (MVP) | Feb 26, 2024 | Syndicated blog

Welcome 2024 Winter OMVPs

Hello, Optimizely community! We are thrilled to announce and welcome the newest members to the Optimizely Most Valuable Professionals (OMVP) progra...

Patrick Lam | Feb 26, 2024

Optimizely Opal... what it does actually do?

At Opticon 2023, Optimizely announced its first AI product Opal. AI is definitely the new tech buzzword in 2024 and with promises that AI will be...

Jon Jones | Feb 25, 2024 | Syndicated blog

How to add more Content Area Context Menu Item in Optimizely CMS 12

Hey folks, today I will share something related to Context Menu customization in the Content Area of Optimizely CMS. As you know, the content area ...

Binh Nguyen | Feb 25, 2024