
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:
//package.json
"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:
//resources/assets/js/bootstrap.js
try {
window.$ = window.jQuery = require('jquery');
require('bootstrap-sass');
require("select2");
require("jsoneditor");
} catch (e) {
console.log("Error loading jquery");
}
Which gets pulled in by my app.js which I also register the global component:
//resources/assets/js/app.js
require('./bootstrap');
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:
//resources/assets/js/components/JSONEditor.vue
<template>
<div>
<div id="jsoneditor"></div>
</div>
</template>
<script>
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); }
}
});
</script>
<style type="text/css">
#jsoneditor {
width: 800px;
height: 600px;
}
</style>
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:
<<template>
<div>
<input type="hidden" id="config" name="config" class="form-control" rows="30" v-model="config">
</div>
</template>
<script>
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);
}
});
</script>
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:
@push('scripts')
<script>
new Vue({
el: '#config_form',
})
</script>
@endpush
<!-- Form above this that is doing all the form submission work -->
<div id="config_form">
<label for="config">Config</label>
<cat-json-editor></cat-json-editor>
<cat-config-field></at-config-field>
</div>
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: