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"
});