JSFiddle - React, Tailwind, and code Playground
by Kingdaro
HTML
<script src="https://unpkg.com/vue"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<div class = "container-fluid" id = "main">
<json-form>
<json-debug></json-debug>
<json-repeat path = "['test']">
<template scope = "parent">
{{parent.index}} - {{parent.item.name}}
</template>
</json-repeat>
</json-form>
</div>
JavaScript
Vue.component("json-form", {
template: `
<form>
<slot :json = "json"></slot>
</form>
`,
created: function() {
this.json = {
"test": [
{
"name": "A"
},
{
"name": "B"
},
{
"name": "C"
}
]
};
},
data: () => {
return {
json: "",
}
}
});
Vue.component("json-repeat", {
props: ["name", "path", "id", "help"],
created: function() {
this.items = eval(`this.$parent.json${this.path}`);
let self = this;
},
template: `
<div :id = "id">
<label :for = "id">{{name}}</label>
<p v-if = "help" class = "help-block" v-html = "help"></p>
<div class = "well" v-for = "item, index in items">
<button type = "button" v-if = "items.length > 1" v-on:click = "removeRow(index)" class = "btn btn-small btn-danger pull-right">
<i class = "fa fa-minus-circle"></i>
</button>
<br />
<slot :item = "item" :index = "index"></slot>
</div>
<button type = "button" v-on:click = "addRow" class = "btn btn-success btn-add-row pull-right"><i class = "fa fa-plus"></i> Add</button>
</div>
`,
data: () => {
return {
initialValue: ""
}
},
methods: {
addRow: function() {
let lastRow = eval(`this.$parent.json${this.path}[this.$parent.json${this.path}.length - 1]`);
lastRow = Object.assign({}, lastRow);
eval(`this.$parent.json${this.path}.push(lastRow)`);
this.$forceUpdate();
},
removeRow: function(index) {
//eval(`this.$parent.json${this.path}.splice(index, 1)`);
eval(`Vue.delete(this.$parent.json${this.path}, index)`);
this.$forceUpdate();
}
}
});
Vue.component("json-debug", {
template: `
<p>{{this.$parent.json}}</p>
`
});
new Vue({
el: "#main"
});