Atomic updates with AngularFire

AngularJS demo app with atomic saves and deletes to Firebase.

by Puigcerber

HTML

<script src="https://cdn.firebase.com/js/client/2.4.1/firebase.js"></script>
<script src="https://cdn.firebase.com/libs/angularfire/1.1.4/angularfire.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.18/angular-ui-router.js"></script>
<script src="https://cdn.firebase.com/libs/firebase-util/0.2.5/firebase-util.min.js"></script>
<div ng-app="webApp">
  <h1>Atomic updates with AngularFire</h1>
  <a ui-sref="home">Home</a>
  <div ui-view=""></div>
  <add-post></add-post>
</div>

CSS

li a {
  margin: 0 2px;
}

JavaScript

angular.module('webApp', ['firebase', 'ui.router'])
  .constant('FBURL', 'https://angular-atomic.firebaseio.com/')
  .service('Ref', ['FBURL', Firebase])
  .service('Blog', Blog)
  .service('PostFactory', PostFactory)
  .directive('postList', postList)
  .directive('addPost', addPost)
  .directive('postForm', postForm)
  .config(routerConfig)
  .run(runBlock);
  
function postList() {
  return {
    restrict: 'E',
    controller: postListCtrl,
    controllerAs: '$ctrl',
    template: [
      '<h2>Post List</h2>',
      '<ul>',
      '<li ng-repeat="post in $ctrl.posts">',
      '{{ post.name }}',
      '<a ng-repeat="(id, tag) in post.tags" ui-sref="tags({tagId: id})">{{ tag.name }}</a>',
      '<button ng-click="$ctrl.deletePost(post)">Delete</button>',
      '</li>',
      '</ul>'
    ].join('')
  }
}

function postListCtrl($stateParams, Blog) {
  var ctrl = this;
  ctrl.deletePost = deletePost;
  
  function onInit() {
    if ($stateParams.tagId) {
      ctrl.posts = Blog.getPostsByTag($stateParams.tagId);
    } else {
      ctrl.posts = Blog.getPosts();
    }   
  }
  
  onInit();
  
  function deletePost(post) {
    Blog.deletePost(post);
  }
}

function addPost() {
  return {
    restrict: 'E',
    controller: addPostCtrl,
    controllerAs: '$ctrl',
    template: [
      '<h3>Add Post</h3>',
      '<post-form post="$ctrl.post" tags="$ctrl.tags" on-save="$ctrl.save(newPost)"></post-form>'   
    ].join('')
  }
}

function addPostCtrl(Blog) {
  var ctrl = this;
  ctrl.save = save;
  
  function onInit() {
    ctrl.tags = Blog.getTags();
  }
  
  onInit();
  
  function save(newPost) {
    Blog.savePost(newPost); 
  }
}

function postForm() {
  return {
    restrict: 'E',
    scope: {},
    bindToController: {
      post: '=',
      tags: '=',
      onSave: '&'
    },
    controller: function() {},
    controllerAs: '$ctrl',
    template: [
      '<form name="$ctrl.postForm">',
      '<div>Name: <input ng-model="$ctrl.post.name" /></div>',
      '<div>Content:...