Dynamic Components in Vue.js

A demo of dynamic components in Vue.js

by Christopher O

HTML

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<div id="app">
  <div class="header clearfix">
    <nav>
      <ul class="nav nav-pills pull-right">
        <li role="presentation">
          <a href="#" @click="currentView='manage-posts'">Manage Posts</a>
        </li>
        <li role="presentation">
          <a href="#" @click="currentView='create-post'">Create Post</a>
        </li>
      </ul>
    </nav>
    <h3 class="text-muted">Admin Panel</h3>
  </div>

  <div class="container">
    <component :is="currentView"></component>
  </div>
</div>

<template id="manage-template">
  <div>
    <h1>Manage Posts</h1>
    <div class="list-group">
      <a v-for="post in posts"
  v-bind:key="post.id"
  v-bind:post="post" href="#" class="list-group-item clearfix">
        {{ post }}
        <span class="pull-right">
          <button class="btn btn-xs btn-info">
            <span class="glyphicon glyphicon-edit"></span>
          </button>
          <button class="btn btn-xs btn-warning">
            <span class="glyphicon glyphicon-trash" v-on:click="delClick(post)"></span>
          </button>
        </span>
      </a>
    </div>
  </div>
</template>

<template id="create-template">
  <div>
    <h1>Create Post</h1>
    <form class="form-horizontal">
      <div class="form-group">
        <label class="col-sm-2 control-label">Post title</label>
        <div class="col-sm-10">
          <input type="text" class="form-control" placeholder="Post title">
        </div>
      </div>
      <div class="form-group">
        <label class="col-sm-2 control-label">Post body</label>
        <div class="col-sm-10">
          <textarea class="form-control" rows="5"></textarea>
        </div>
      </div>
      <div class="form-group">
        <div class="col-sm-offset-2 col-sm-10">
          <button type="submit" class="btn btn-primary">Create</button>
        </div>
      </div>
    </form>
  </div>
</template>

CSS

.header {
  padding: 15px 15px 20px 15px;
  border-bottom: 1px solid #e5e5e5;
}

.header h3 {
  margin-top: 0;
  margin-bottom: 0;
  line-height: 40px;
}

JavaScript

Vue.component('manage-posts', {
	props: ['post'],
  template: '#manage-template',
/*   data: function() {
    return {
      posts: [
        'Vue.js: The Basics',
        'Vue.js Components',
        'Server Side Rendering with Vue',
        'Vue + Firebase'
      ]
    }
  }, */
  methods: {
    delClick(post){
      console.log("Delete Clicked: " + post);
      // Delete one record
      // Vue.delete( this.$parent.$data.head, id );
      // vm1.headDelClick(id);
    },
  },
})

Vue.component('create-post', {
  template: '#create-template'
})

var vm1 = new Vue({
  el: '#app',
  data: {
    currentView: 'manage-posts',
    posts: [
      { id: 1, title: 'My journey with Vue' },
      { id: 2, title: 'Blogging with Vue' },
      { id: 3, title: 'Why Vue is so fun' }
    ]
  }
})