Vue.js, Sitecore MVC and the Experience Editor

September 18, 2019
2 min read

There is a compatibility issue between Vue.js and Sitecore MVC experience editor with Sitecore 9.1. This issue is with a standard Sitecore MVC solution rather than Sitecore JSS.

The Problem

The problem occurs when adding a new component in experience editor. The problem manifests itself by appearing to ignore placeholder settings and show you the treeview for selecting a rendering:

Select a rendering

The browser then displays an alert saying "An error occurred." and the following in your logs:

Exception: System.InvalidOperationException
Message: placeholderKey
Source: Sitecore.ExperienceEditor
   at Sitecore.Pipelines.ExecutePageEditorAction.InsertRendering.Process(PipelineArgs args)
   at (Object , Object )
   at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args)
   at Sitecore.Pipelines.DefaultCorePipelineManager.Run(String pipelineName, PipelineArgs args, String pipelineDomain, Boolean failIfNotExists)
   at Sitecore.Pipelines.DefaultCorePipelineManager.Run(String pipelineName, PipelineArgs args, String pipelineDomain)
   at Sitecore.Pipelines.ExecutePageEditorAction.ExecutePageEditorActionPipeline.Run(ExecutePageEditorActionArgs args)
   at Sitecore.Shell.Applications.WebEdit.Palette.OnPreInit(EventArgs e)
   at System.Web.UI.Page.PerformPreInit()
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

Why does this happen?

The reason this happens is because both Sitecore and Vue.js need to use a key attribute.

  • For Vue.js, the key attribute is a special attribute:
  • For Sitecore, the key attribute is used on the placeholder DOM elements added to the page in experience editor

With both Vue.js and Experience Editor together, Vue.js removes the key attribute so when you add a new component, Sitecore doesn't know which placeholder you are adding it to.

The Solution

A solution to resolve this was to create an adapter in JavaScript, which does the following:

  1. Find all Sitecore placeholders and copy the key attribute to a new attribute, data-phkey
  2. Execute the standard Vue.js app initialisation code.
  3. Copy the value from the new data-phkey attribute back to the key. attribute

Here is the code to register the Vue.js app with the new adapter:

    new Vue({
        el: "#app",
        components: {
export default class SitecoreModeService
    public IsExperienceEditor(): boolean
        if(typeof(Sitecore) === "undefined")
            return false;

        return !!(Sitecore && Sitecore.PageModes && Sitecore.PageModes.PageEditor);
export class SitecoreVueApdater
    private readonly _sitecoreModeService: SitecoreModeService;
    private readonly _keyAttributeName = "key";
    private readonly _tempKeyAttributeName = "data-phkey";

    public constructor()
        this._sitecoreModeService = new SitecoreModeService();

    public InitialiseVueApp(
        initialiseVueApp: () => void
    ): void

    private BuildSitecorePlaceholderMap(): void
            const pagePlaceholders = document.querySelectorAll(`code[${this._keyAttributeName}]`);

            this.CopyElementsAttribute(pagePlaceholders, this._keyAttributeName, this._tempKeyAttributeName);

    private EnsureSitecorePlaceholderKeys(): void
            const pagePlaceholders = document.querySelectorAll(`code[${this._tempKeyAttributeName}]`);

            this.CopyElementsAttribute(pagePlaceholders, this._tempKeyAttributeName, this._keyAttributeName, true);

    private CopyElementsAttribute(
        elements: NodeListOf<Element>,
        fromAttributeName: string,
        toAttributeName: string,
        removeFromAttribute = false): void
        for(const placeholder of elements)
            placeholder.setAttribute(toAttributeName, placeholder.getAttribute(fromAttributeName) || "");