<!DOCTYPE html>
<html ng-app="userapp">
  <head>
    <title>Angular + DataTable Demo</title>
    <meta name="description" content="Angular Table demo" />
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.10/angular.min.js"></script>
    <link href="//datatables.net/download/build/nightly/jquery.dataTables.css" rel="stylesheet" type="text/css" />
    <script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="//datatables.net/download/build/nightly/jquery.dataTables.js"></script>
    <script src="https://builds.handlebarsjs.com.s3.amazonaws.com/handlebars-v1.3.0.js"></script>
    <!--
      Lets assume angular user-link's are reused in many places,
      not just in tables.
     -->
    <script id="userLinkTemplate" type="text/ng-template">
      <a href="http://server/edit?user={{user.ID}}">Edit</a>
    </script>
    <!--
      Unfortunately, I can't use the angular template inside tables, so I need to
      duplicate the display logic e.g. for user links. ( I could have gone with simple 
      old-style string concatenation, but prefer Handlebars instead. )
      By coincidence, the angular and Handlebar templates are exactly identical
      but the handlebar ones are way, way less powerful,
      and duplication is needed in the general case, which is so sad! :-(
    -->
    <script id="userLinkHandlebarTemplate" type="text/x-handlebars-template">
      <a href="http://server/edit?user={{user.ID}}">Edit</a>
    </script>
    
  </head>
    <body ng-controller="TableDemoCtrl" ng-cloak>
      <p><i>See comment at top of JavaScript file for description</i></p>
      <p>
        <!-- 
           The magic of AngularJS for me is that this "just works"
           The angular table is automatically updated
        -->
        <button ng-click="addUserCB()">Add User</button>
      </p>
      <!-- First a DataTable table and then a raw Angular table -->
      
      <h2>DataTable</h2>
      <table id="dataTable">
        <thead>
          <tr>
            <th>Edit</th>
            <th>Name</th>
            <th>Position</th>
          </tr>
        </thead>
        <!-- DataTable: code to add all tbody data/rows in javascript -->
      </table>
      
      <h2>Angular Table</h2>
      <table id="angular-has-no-need-for-an-id">
        <thead>
          <tr>
            <th>Edit</th>
            <th>Name</th>
            <th>Position</th>
          </tr>
        </thead>
        <!-- Angular: code to add all tbody data/rows right here -->
        <tbody>
          <tr ng-repeat="user in users" user="user">
            <td>
              <div user-link="user"></div>
            </td>
            <td>{{user.name}}</td>
            <td>{{user.position}}</td>        
          </tr>
        </tbody>              
      </table>
      
      <!-- See how all the logic for this is right here -->
      <p ng-show="users.length">
        Here is a link for the first user: <span user-link="users[0]"></span>
      </p>
    </body>
</html>
 
/*
  
  Here we show a Datatables+Handlebars table and 
  a raw AngularJS table.
  
  We'll pretend we want to show some users (from /ajax/objects.txt)
  With AngularJS, the javascript is reduced to bindings and glue only.
  In the Angular parts of this example, *all* actual view logic
  - how the users are displayed - 
  is in the HTML section, none of it here. Here we *only* deal with model 
  data
  
  The dataTable is updated by "watching" a variable for changes,
  and when it changes, 
  dataTable.clear().rows.add(data).draw()
  The logic that generates data knows view specific things,
  such as the columns in the table and which templates to use where.
  
  Most importantly, I can't use any of the Angular functionality inside 
  my table, creating a non-Angular island in my application, where I need 
  to duplicate the angular functionality I already have implemented.
  (See the HTML file / "pane" for more comments)
  The same data is used in both tables:
  
  We get /ajax/objects.txt that has 57 employees.
  Lets use them as a pool of employees, pretend we start with 1
  and have a button where we can add more
  from the remainder of the original 57 
*/
var INITIAL_USERS = 1;
/*
  If this != null, the datatable has been initialized
*/
var dataTable;
/*
*/
angular
.module("userapp", [])
.controller('TableDemoCtrl', function ($scope, $http) {
  /*
    GET /ajax/objects.txt and setup the initial 10 $scope.users and put the remainder 
    in remainingUsers so we have a pool to add new ones from
  */
  var remainingUsers = [];
  $scope.users = [];
  
  $http({
    method: 'GET',
    url: '/ajax/objects.txt',
    responseType: 'json'
  }).then(function (result) {
    var allUsers = result.data.data;
    allUsers.forEach(function (user) {
      // Lets pretend that what in objects.txt is .extn
      // is actually a user ID
      user.ID = user.extn;
      delete user.extn;
    });
    $scope.users = allUsers.splice(0,INITIAL_USERS);
  
    remainingUsers = allUsers;
  });
  
  // We make var users available as a $scope member
  $scope.addUserCB = function () {
    // Just take one more user from remainingUsers
    // Note how this is *all* that is required for the Angular raw table to get updated correctly?
    $scope.users.push(remainingUsers.shift());
  };
  
  $scope.$watch('users', function () {
    setupDataTableUsers($scope.users);
  }, true);
  
  // For debugging in the console :-)
  // window.s = $scope;
})
// Pure boilerplate that ties the user-link attribute with the #userLinkTemplate
.directive('userLink', function() {
  return {
    restrict: 'A',
    scope: {
      user: '=userLink'
    },
    templateUrl: 'userLinkTemplate'
  };
});
/*
  Now for the Handlebars / DataTable javascript setup
  Notice how most of the view logic is here in javascript.
  Here we decide what columns are in the table and what each column contains.
*/
var linkTemplate = Handlebars.compile(
  jQuery('#userLinkHandlebarTemplate').html()
);
function setupDataTableUsers(users) {
  if (! dataTable)
    return;
  // Don't want to pollute the pristine users field with a view-specific 'edit'
  // field that contains HTML, but we do want HTML in the table
  var dataTableUsers = users.map(function (user) {
    var userClone = jQuery.extend({}, user);
    userClone.edit = linkTemplate({ID: user.ID});
    return userClone;
  });
  
  /*
    How does this perform if there are many users? 
    Is there a better way than removing everything and adding it all back?
  */
  dataTable
    .clear()
    .rows.add(dataTableUsers)
    .draw();
}
jQuery(function () {
  dataTable = jQuery('#dataTable').DataTable({
    columns: [
      { data: "edit" },
      { data: "name" },
      { data: "position" }
    ]
  });
});
Output 300px

You can jump to the latest bin by adding /latest to your URL

Dismiss x
public
Bin info
anonymouspro
0viewers