AngularJS CRUD Operations over a REST service (NodeJS)

Esteban Fernández


The sample have two important components, the first is an AngularJS client and the second is a service implemented in NodeJS. The second part will be explained in a future article, but the important thing here is that both parts can work (and be implemented) separately.

In this article we have explored the create, update and delete operations, but the read method wasn’t implemented, so we don't completed the whole CRUD operations. The team decided study and document a sample that represents entities of ATMs. This entity has name, address and state as string attributes plus two booleans that set if the ATM accept deposits and if it has restricted services (called mini).

CRUD View

Code of the view:

<h3>Add/Edit ATMs</h3>
<form class="form" role="form">
<div class="form-group">
<label class="sr-only" for="InputName">Name</label>
<input type="text" ng-model="atm.name" class="form-control" id="InputName" placeholder="Name" >
</div>
<div class="form-group">
<label class="sr-only" for="InputAddress">Address</label>
<input type="text" ng-model="atm.address" class="form-control" id="InputAddress" placeholder="Address" >
</div>
<select class="form-control" ng-model="atm.state_id" ng-options="state_id.name for state_id in states track by state_id._id" >
<option value="" >Choose state</option>
</select>
<div class="checkbox">
<label>
<input type="checkbox" ng-model="atm.acceptDeposits" > Accept deposit?
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox" ng-model="atm.isMini" > Is mini?
</label>
</div>
<button type="submit" class="btn btn-default" ng-click="addItem()" >Add</button>
<button type="submit" class="btn btn-default" ng-click="editItem()" ng-disabled="selectedAtm < 0" >Edit</button>
</form>
<br>
<h3>List ATMs</h3>
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th class="text-center" >Name</th>
<th class="text-center" >Address</th>
<th class="text-center" >State</th>
<th class="text-center" >Deposit?</th>
<th class="text-center" >Is mini?</th>
<th>
</tr>
</thead>
<tbody>
<tr class="text-center" ng-repeat="atm in atms" ng-click="setSelected($index)">
<td>{{atm.name}}</td>
<td>{{atm.address}}</td>
<td>{{atm.state_id.name}}</td>
<td>
<span ng-class="{'glyphicon glyphicon-ok': atm.acceptDeposits,'glyphicon glyphicon-remove': !atm.acceptDeposits }" >
</td>
<td>
<span ng-class="{'glyphicon glyphicon-ok': atm.isMini,'glyphicon glyphicon-remove': !atm.isMini }" >
</td>
<td>
<button type="submit" class="btn btn-default" ng-click="deleteItem(atm._id,$index)" >
<span class="glyphicon glyphicon-trash" >
</button>
</td>
</tr>
<tbody>
</table>

This view have a bunch of directives that are represented with the format 'ng-xxxxxx', you can see specific information here: https://docs.angularjs.org/guide/concepts#directive.

To create an ATM you need to build a form. You can see in the above code that the mapping between the entity and the form is very natural. You only need to link each ATM property with an input tag using the ng-model directive. Finally you need to call a method to make the input values persistent, which can be done using the ng-click directive with the method name “addItem” as value. Both properties and method are located in the entity controller which will be described forward.

To read the entity we have made a mapping under the “List ATMs” title. The list is bound with the directive ng-repeat to the list of ATMs that is inside the controller. The atm used in the table binding is the generic name that takes every element of the atm list in each loop. The double curly braces {{}} expression is the way to tell angular that you want to render some property of the atm object.

About the update of an entity, we used the same form as the one used for creating it. The main difference is that you need to select the entity from the table (click over it) to perform the read operation before you can update it. For this purpose there is a ng-click directive with “setSelected” value that call that event to select an ATM and let the form be bound. Then, there is a button associated with the “editItem” method defined inside the controller.

The last implemented operation is the Delete. In this case you have one button associated for each item of ATMs list, and this button is bound with the directive ng-click with the “deleteItem” method of the controller.

We need to add the view source in a relative path /app/views/partials/atms.html so the partial can be bound using the ng-view directive: <div class="container" ng-view=""></div>

CRUD Controller

This is the controller for this sample:

angular.module('atmApp')
  .controller('AtmCtrl', function($scope, Atm, State) {
    /* Auxiliar functions */
    function clearAtm(){
      $scope.selectedAtm = -1;
      $scope.atm = {};
    }

    /* Dom functions */
    clearAtm();

    $scope.setSelected = function($index) {
      $scope.selectedAtm =  $index;
      $scope.atm = angular.copy($scope.atms[$index]);
    };

    /* ATM CRUD */
    $scope.atms = Atm.query();
    $scope.states = State.query();

    $scope.addItem = function() {
      $scope.atms.push(Atm.save({},$scope.atm));
      clearAtm();
    };

    $scope.editItem = function() {
      $scope.atms[ $scope.selectedAtm] = Atm.save({id: $scope.atm._id},$scope.atm);
      clearAtm();
    };

    $scope.deleteItem = function(atmId,$index) {
      $scope.atms.splice($index,1);
      Atm.delete({id: atmId});
      if($scope.selectedAtm == $index){
        clearAtm();
      }
    };
});

The controller has all the entities initialization code and also the functions we need to manage them. As you can see in the code, the controller receives two factories by param and they are responsible for the creation of the resources to consume the rest endpoint. We recommend the reading of this article that is a similar case of study: http://www.sitepoint.com/creating-crud-app-minutes-angulars-resource/.

The Create operation  ($scope.addItem) calls the save method of the factory that receives as params an empty object {} and the entity. The first (empty) parameter indicates that it doesn’t have an existent id and the second is the entity to be persisted. The save method will end sending this information as a restful request to the server.

In the case of Update operation ($scope.editItem), it calls the same save method as before but receiving the {id} of the entity to be modified as a first parameter. The information is sent as a restful request too.

The Destroy operation ($scope.deleteItem) calls the delete method of the factory passing the {id} of the object to be deleted. As usual, the request is sent as a restful one.

We need to add the controller inclusion in a relative path /app/scripts/controller/atm.js.

Conclusion

This article shows a very simple CRUD sample using AngularJS. You can get access to the complete source code here: https://github.com/vairix-pvilas/atm.



How to contact us

Our Location

DireccionArismendi 1420 Of. 102 Telefono(+598) 2409 15 66 Mailinfo@vairix.com

Follow us


Want to contact us?