posted by jwerner on Friday, August 8, 2014 1:18 PM

This tutorial explains using angular-florm, an object-relational mapper with Angular.js.

Introduction

We will create a small angular.js app which shows a list of users.

A user has the properties firstName, lastName and password.

We want to add new users as well as modify existing users and also delete users.

Requirements

Bootstrapping the Project

Install angular-seed:

git clone https://github.com/angular/angular-seed.git angular-florm
cd angular-florm

angular-seed has preconfigured npm to automatically run bower so we can simply install the required components:

npm install

Install angular-florm:

bower install --save angular-florm

The --save option will add angular-florm to the bower.jsonfile.

Adding Routes

Edit the file js/app.js:

'use strict';
 
// Declare app level module which depends on filters, and services
angular.module('myApp', [
  'ngRoute',
 
  // add angular-florm:
  'ngFlorm',
 
  'myApp.filters',
  'myApp.services',
  'myApp.directives',
  'myApp.controllers'
]).
config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/view1', {templateUrl: 'partials/partial1.html', controller: 'MyCtrl1'});
  $routeProvider.when('/view2', {templateUrl: 'partials/partial2.html', controller: 'MyCtrl2'});
 
  // add routes for users
 
  // list view
  $routeProvider.when('/users', {templateUrl: 'partials/users/list.html', controller: 'UsersCtrl'});
 
  // add new user:
  $routeProvider.when('/users/add', {templateUrl: 'partials/users/form.html', controller: 'UsersCtrl'});
 
  // edit existing user:
  $routeProvider.when('/users/:id', {templateUrl: 'partials/users/form.html', controller: 'UsersCtrl'});
  $routeProvider.otherwise({redirectTo: '/view1'});
}]);

Creating the Controller

Edit app/js/controllers.js:

angular.module('myApp.controllers', [])
  .controller('MyCtrl1', ['$scope', function($scope) {
 
  }])
  .controller('MyCtrl2', ['$scope', function($scope) {
 
  }])
  // Users controller:
  .controller('UsersCtrl', ['$scope', '$routeParams', '$location', function($scope, $routeParams, $location) {
 
    // Initiate florm
    var $florm = angular.injector(['myApp']).get('$florm');
 
    // Get Users ORM
    var Users  = $florm('users');
 
    // Set default title and button tag
    $scope.title="Add User";
    $scope.submitButton="Create";
 
    // Edit an existing user?
    if ($routeParams.id) {
        // Get user object
        $scope.user = Users.find($routeParams.id);
        // Change title and button tag
        $scope.title="Edit User";
        $scope.submitButton="Update";
    // Add new user?
    } else if($location.path() === '/users/add') {
        $scope.user = Users.new({name: '', password : ''});
    }
 
    // Get all users objects
    $scope.users = Users.all();
 
    // sort by firstName
    $scope.users.sort(dynamicSort('firstName'));
 
    // [Add User] button clicked
    $scope.addUser = function () {
        $location.path('/users/add');
    };
 
    // [Create/Update] button clicked
    $scope.save = function () {
        $scope.user.save();
        $location.path('/users');
    };
 
    // [Cancel] button clicked
    $scope.cancel = function () {
        $location.path('/users');
    };
 
    // _Delete_ link clicked
    $scope.delete = function (id) {
        if (!confirm('Confirm delete')) {
            return false;
        }
        // delete user
        Users.find(id).delete();
        // get all users
        $scope.users = Users.all();
        $scope.users.sort(dynamicSort('firstName'));
    };
 
  }]);
 
// Sort object s dynamically by a property
function dynamicSort(property) {
    var sortOrder = 1;
    if(property[0] === "-") {
        sortOrder = -1;
        property = property.substr(1);
    }
    return function (a,b) {
        var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
        return result * sortOrder;
    }
}

Creating the Page Layout

Edit the file app/index.html:

...
<body>
  <div class="header">
  <h1>FLORM Example</h1>
  <ul class="menu">
    <li><a href="#/view1">view1</a></li>
    <li><a href="#/view2">view2</a></li>
 
    <!-- Add a new 'tab': -->
    <li><a href="#/users">Users</a></li>
  </ul>
  </div>
  <!--[if lt IE 7]>
  ...
  <![endif]-->
 
  <!-- add a class and ng-animate: -->
  <div class="myview" ng-view ng-animate="{enter: 'fade-enter'}"></div>
 
<footer>
    <hr />
    <div>Angular seed app: v<span app-version></span></div>
</footer>
 
...
  <script src="bower_components/angular-route/angular-route.js"></script>
 
  <!-- Add angular-florm: -->
  <script src="bower_components/angular-florm/lib/angular-florm.js"></script>
 
  ...
</body>

Creating the List View

Create the file app/partials/users/list.html:

<h2>Users List</h2>
<div class="actionBar">
    <button type="button" ng-click="addUser()">Add User</button>
    <form><input id="textinput" name="textinput" placeholder="Search" class="input-xlarge" type="text" ng-model="searchText" autoFocus /></form>
</div>
<table class="mytable">
    <thead>
        <tr>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Actions</th>
        </tr>
    </thead>
    <tbody>
    <tr ng-repeat="user in users | filter:searchText">
        <td>{{user.firstName}}</td>
        <td>{{user.lastName}}</td>
        <td>
            <a href="#/users/{{user.id}}">Edit</a>
            <a href="#/users" ng-click="delete(user.id)">Delete</a>
        </td>
    </tr>
    </tbody>
</table>

Creating the Form View

Create the file app/partials/users/form.html:

<h2>{{title}}</h2>
<form ng-submit="save()">
    <label for="firstName">First Name:</label>&nbsp;
    <input type="text" name="firstName" placeholder="First Name" size="20" ng-model="user.firstName" required autoFocus /><br />
    <label for="lastName">Last Name:</label>&nbsp;
    <input type="text" name="lastName" placeholder="Last Name" size="20" ng-model="user.lastName" required /><br />
    <label for="password">Password:</label>&nbsp;
    <input type="password" name="password" size="20" ng-model="user.password" required /><br />
    <hr />
    <button type="submit">{{submitButton}}</button>
    <button type="button" ng-click="cancel()">Cancel</button>
</form>

Adding an autoFocus Directive

Edit the file app/js/directives.js:

angular.module('myApp.directives', []).
  directive('appVersion', ['version', function(version) {
    return function(scope, elm, attrs) {
      elm.text(version);
    };
  }])
  .directive('autoFocus', function($timeout) {
    return {
        restrict: 'AC',
        link: function(_scope, _element) {
            $timeout(function(){
                _element[0].focus();
            }, 0);
        }
    };
  });

Running the Application

Open a console window and enter

npm start

Open http://localhost:8000/app in your browser - enjoy!

Screenshots

GALLERY_1

Comments

No comments


Please enter the letters as they are shown in the image above.
Letters are not case-sensitive.

Add comment

Change Log

Created OnAug 8, 2014 1:18:14 PM CEST
Created ByJoachim Werner (jwerner)
Updated OnAug 13, 2014 1:54:04 PM CEST
Updated ByJoachim Werner (jwerner)