Search code examples
javascriptdjangovue.jsvuejs2django-cms

Use django-cms with VueJS broke the front-end editing


I try to create a sample app using django-cms and VueJS.

<body>
    {% cms_toolbar %}
    <div class="container">
        <div id="vue-wrapper">
            <div class="content">
                {% block content %}{% endblock content %}
            </div>
        </div>
    </div>
    {% render_block "js" %}
    <script src="https://unpkg.com/vue"></script>
    <script>
        const app = new Vue({
            el: '#vue-wrapper',
            mounted: () => {
                console.log("mounted")
            },
        })
    </script>
</body>

This simple code broke the front-end editing.

If I remove the vue-wrapper element, comment the js code, or close the element before it wrapping my content, the front-end editing works.

I don't understand why wrapping with Vue broke this, and if it's possible, how I can fix.


Solution

  • This happens because django-cms uses the <template> tags to wrap it's plugins into .cms-plugin div's when in structure mode. That adds the double click to edit link to the actual plugin.

    Since Vue uses the <template> tags to specify templates outside javascript, it parses them and remove's their content. Thats why the "double click to edit" feature is gone.

    I've wrote a simple patch for this that wraps django-cms plugins in <cms-template> tags which when included in Vue.config.ignoredElements ensure the cms-plugin div's remain after vue have processed the html.

    You can find the patch here: https://gist.github.com/dinoperovic/a719f0c43a2614f434a309b64a64e18f

    Simply load the script and do this in your js:

    // app.js
    
    // Set ignored elements as required by vue-djangocms-patch.
    Vue.config.ignoredElements = ['cms-template', 'cms-plugin'];
    
    // Main Vue instance.
    var app = new Vue({
      el: '#app',
      created: function () {
        new VueDjangoCMSPatch(this);
      }
    });
    

    Hope this helps.

    Cheers!

    Dino.