Vue 101

by Admiral Potato

HTML

<script src="https://unpkg.com/vue@2"></script>
<div id="app">
  	<h1>How many goats: {{ goatCount }}</h1>
    <goat-editor
      class="goat-detail"
      v-for="item in goats"
      :goat="item"
    ></goat-editor>
    <div>
      <hr />
      <h2>Debug</h2>
      <pre>{{ debug }}</pre>
    </div>
</div>

<div
  style="display: none;"
  id="template-goat-editor"
>
  <div class="goat-editor">
		<button
			class="collpase"
			@click="collapsed = !collapsed"
		>x</button>
    <h3>Name: {{ goat.name }}</h3>
    <ul
			v-if="!collapsed"
		>
      <li>age: <input v-model.number="age"></li>
      <li>is_grumpy: {{ goat.is_grumpy }}</li>
    </ul>
  </div>
</div>

CSS

.goat-editor {
	border: 2px solid #444;
	position: relative;
}

.goat-editor .collpase {
	position: absolute;
	top: 10px;
	right: 10px;
}

JavaScript

Vue.component(
	'goat-editor',
  {
  	template: "#template-goat-editor",
    props: {
    	goat: {
      	type: Object,
        required: true,
      }
    },
		data: function () {
			return {
				collapsed: false,
			}
		},
    computed: {
    	age: {
      	get: function () {
        	return this.goat.age
        },
        set: function (value) {
        	this.$emit(
          	'update:goat',
          	Object.assign(
            	{},
              this.goat,
              {
              	age: value
              }
            )
          )
        }
      }
    }
  }
)

var application = new Vue({
	el: "#app",
  data: {
  	goats: [
    	{
      	name: "Gruff",
        age: 99,
        is_grumpy: true,
      },
    	{
      	name: "Faun",
        age: 18,
        is_grumpy: false,
      },
    	{
      	name: "Billy",
        age: 5,
        is_grumpy: false,
      }
    ],
  },
  computed: {
  	goatCount: function () {
    	return this.goats.length;
    },
    debug: function () {
    	return JSON.stringify(
      	this.goats,
        null,
        '\t',
      );
    }
  },
  methods: {
  }
});