Angular Copy

An example of using Angular copy for a crud application.

by Rob Rothe

HTML

<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<div ng-app="app">
  <div ng-controller="FormCtrl as form_ctrl">
    <form class="form-inline" ng-submit="form_ctrl.save()">
      <div class="form-group">
        <input type="text" ng-model="form_ctrl.form_data.name" class="form-control" placeholder="Person">
      </div>
      <div class="form-group">
        <input type="text" ng-model="form_ctrl.form_data.band" class="form-control" placeholder="Band">
      </div>
      <button type="submit" class="btn btn-primary" ng-disabled="form_ctrl.disable_save">Save</button>
      <button type="button" class="btn btn-default" ng-click="form_ctrl.cancel()">Cancel</button>
    </form>
  </div>

  <div ng-controller="ListCtrl as list_ctrl">
    <table class="table">
      <tr ng-repeat="m in list_ctrl.musicians | orderBy:'name'">
        <td>{{m.id}}</td>
        <td>{{m.name}}</td>
        <td>{{m.band}}</td>
        <td>
          <button ng-click="list_ctrl.edit(m)" class="btn btn-link">Edit</button>
        </td>
      </tr>
    </table>
  </div>
</div>

CSS

body {
  padding:20px;
}

form {
  margin-bottom:20px;
}

JavaScript

(function() {

  'use strict';

  angular
    .module('app', [])
    .controller('ListCtrl', ListCtrl)
    .controller('FormCtrl', FormCtrl)
    .factory('Data', Data);

  function FormCtrl(Data, $scope) {
    var vm = this;

    vm.form_data = {},
      vm.save = save;
    vm.cancel = cancel;

    $scope.$on('new_form_data', function(event, data) {
      vm.form_data = data;
    });

    $scope.$watch(angular.bind(vm.form_data, function() {
      vm.disable_save = true;

      if (vm.form_data.name && vm.form_data.band) {
        vm.disable_save = false;
      }

    }));

    function save() {
      Data.save(vm.form_data);
      vm.cancel();
    }

    function cancel() {
      vm.form_data = {};
    }
  }

  function ListCtrl(Data, $rootScope) {
    var vm = this;
    vm.musicians = Data.musicians;
    vm.edit = edit;

    function edit(musician) {
      var form_data = Data.copy(musician);
      $rootScope.$broadcast('new_form_data', form_data);
    }
  }

  function Data() {
    var service = {
      musicians: [{
        id: 1,
        name: 'Jimmy Page',
        band: 'Led Zeppelin'
      }, {
        id: 2,
        name: 'Geezer Butler',
        band: 'Black Sabbath'
      }, {
        id: 3,
        name: 'Tom Araya',
        band: 'Slayer'
      }, {
        id: 4,
        name: 'Robin Crosby',
        band: 'Ratt'
      }],
      copy: copy,
      save: save
    };

    return service;

    function copy(musician) {
      var idx = this.musicians.indexOf(musician);
      musician.idx = idx;
      return angular.copy(musician);
    }

    function save(musician) {
      if (musician.id) { // existing record so update the model
        var idx = musician.idx;
        service.musicians[idx] = musician;
      } else { // new record so add to the model
        var id;
        Math.max.apply(Math, service.musicians.map(function(o) {
          // used to get the last id in the model and increase it by 1
          id = o.id + 1
        }));

       ...