Wrapping JSONEditor in Vue as Well as Laravel Blade

Posted: 2017-11-01 12:11:50

UPDATED November 05 2017

This will cover how to make a JSONEditor component that I can then use in a Blade template and listen to events.

You will end up with this:

First making sure I have all the packages I need:

  "devDependencies": {
    "axios": "^0.17",
    "bootstrap-sass": "^3.3.7",
    "cross-env": "^5.0.1",
    "jquery": "^3.2",
    "laravel-mix": "^1.0",
    "lodash": "^4.17.4",
    "vue": "^2.1.10"
  "dependencies": {
    "select2": "^4.0.5",
    "jsoneditor": "^5.9.6"

And to load it into my bootstrap file:

try {
    window.$ = window.jQuery = require('jquery');
} catch (e) {
    console.log("Error loading jquery");

Which gets pulled in by my app.js which I also register the global component:


window.Vue = require('vue');

  * Using this as a globle event emmitter for components to easily talk to other components
window.EventBus = new Vue();

Vue.component('cat-json-editor', require('./components/JSONEditor'));

Vue.component('cat-config-field', require('./components/ConfigField'));
//end of file

The app.js and bootstrap.js are default workflows of Laravel

Then I will make the component:

        <div id="jsoneditor"></div>


    import JSONEditor from 'jsoneditor';

    export default Vue.extend({
        props: ['config'],

        mounted: function () {
            let self = this;
            let container = document.getElementById('jsoneditor');
            let options = {
                onChange: function() {
                    EventBus.$emit('config-updated', editor.get());
                modes: ["tree", "text"],
            let editor = (container) ? new JSONEditor(container, options) : null;
            if(container) { editor.set(window.config); }

<style type="text/css">
    #jsoneditor {
        width: 800px;
        height: 600px;

Here I register the props and I setup some config using code I placed into window from my controller. You can use this tool for this process. I could have passed it into the component but chose not to.

So now when there is a change it will emit the change to the global EventBus

Now for the ConfigField component:

        <input type="hidden" id="config" name="config" class="form-control" rows="30" v-model="config">


    export default Vue.extend({

        data() {
            return {
                'config': JSON.stringify(window.config)

        methods: {
            configUpdated: function(json) {
                this.config = JSON.stringify(json);

        created() {
            EventBus.$on("config-updated", this.configUpdated);



With these two components in place I now need to add the components to the HTML template.

After this is setup my Blade file has the needed Vue listener etc to update the form (non-ajax) as needed:

        new Vue({
            el: '#config_form',

<!-- Form above this that is doing all the form submission work -->
<div id="config_form">
    <label for="config">Config</label>

In this case I am taking advantage of Blades stack feature

And the minor amount of work here just mounts Vue onto the #config_form

Then I use Vue to listen to the event "config-updated". From there, since this is not about Ajax requests, I update the hidden field on the form. I could have done this with JQuery but just wanted to get use to this Vue workflow. Also I could see sending this over Ajax sooner than later even if just for validation notices etc.

Here is a quick look at the Scope of the objects: