1

I'm using jqueryDataTables to sort data in tables in my app.

Rather then using a script tag on the page which it needs to be on, figured I could just include it inside of my Angular Controller code for that view, however I'm and getting a strange error.

I've used a mix of jQuery before inside of Angular, so not sure why it's not working in this case.

Error and code below: TypeError: Cannot read property 'childNodes' of undefined enter image description here

// Controller for Manage Users
app.controller('ManageUsersController', function($scope) {

    // Init
    $scope.status_dropdown = false;
    $scope.deactivate_btn = false;

    // Check all users:
    this.checkAll = function(target) {
        var checkboxes = document.getElementsByName('checkboxUser');
        var checkAll = document.getElementsByName('checkboxAll');

        for(var i=0, n=checkboxes.length;i<n;i++) {
            checkboxes[i].checked = checkAll[0].checked;
        }
    };

    alert('1');
    $('#manage_users_table').DataTable();
    alert('2');
});

HTML during first alert message: enter image description here

HTML during 2nd alert message, after DataTable() has been initialized: enter image description here

The alert pops up twice for each.

HTML
Gist: https://gist.github.com/leongaban/4f1de6bee8672b4177e5

<div id="manage_content" class="page" ng-controller="ManageUsersController as manageUsers">
    <table id="manage_users_table" width="100%">
        <tr>... hardcoded table data here



    <!-- PRODUCTION SCRIPTS -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

    <!-- DEVELOPMENT SCRIPTS -->
    <!-- Libs & Vendors -->
    <script src="src/js/libs/angular.min.js"></script>
    <script src="src/js/libs/angular-route.min.js"></script>
    <script src="src/js/libs/jquery.dataTables.js"></script>
    <script src="src/js/vendors/modernizr.min.js"></script>
    <script src="src/js/vendors/bootstrap.min.js"></script>

    <!-- Modules -->
    <script src="src/js/modules/app.js"></script>
    <script src="src/js/modules/products.js"></script>
    <script src="src/js/modules/manage.js"></script>
    <script src="src/js/modules/profile.js"></script>
</body>
Leon Gaban
  • 36,509
  • 115
  • 332
  • 529

3 Answers3

1

Seems like this previous response didnt return data, which used to fill table. So You are trying to attach datatables script to empty table.

So I am assume error somewhere in loading table contents.

Small example with static data:

<html ng-app="someApp">
<head>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
    <!-- DataTables CSS -->
    <link rel="stylesheet" type="text/css" href="//cdn.datatables.net/1.10.3/css/jquery.dataTables.css">
    <!-- jQuery -->
    <script type="text/javascript" charset="utf8" src="//code.jquery.com/jquery-1.10.2.min.js"></script>
    <!-- DataTables -->
    <script type="text/javascript" charset="utf8" src="//cdn.datatables.net/1.10.3/js/jquery.dataTables.js"></script>
</head>
<body>
  <div ng-controller="ManageUsersController">
        <table id="manage_users_table" class="display">
            <thead>
                <tr>
                    <th>Column 1</th>
                    <th>Column 2</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>Row 1 Data 1</td>
                    <td>Row 1 Data 2</td>
                </tr>
                <tr>
                    <td>Row 2 Data 1</td>
                    <td>Row 2 Data 2</td>
                </tr>
            </tbody>
        </table>
  </div>
  <script type="text/javascript">
    var app = angular.module('someApp', []);
    app.controller('ManageUsersController', function($scope) {
        $('#manage_users_table').DataTable(); // <-- errors
    });
  </script>
</body>
</html>
omakoleg
  • 539
  • 4
  • 6
  • 1
    Could You provide html for the page? For an example paste it here: https://gist.github.com/ – omakoleg Oct 13 '14 at 20:03
  • Ah cool! I'll use that more often now, here is the link: https://gist.github.com/leongaban/4f1de6bee8672b4177e5 Do you need the Angular module as well? – Leon Gaban Oct 13 '14 at 21:40
  • 1
    I think all issues are because of this:
    You have same class name and the ID for table. Change class name and hopefully You will not see errors any more.
    – omakoleg Oct 14 '14 at 07:54
  • Ah interesting, so I removed the script tag form the template, changed the class name and uncommented the `$('#manage_users_table').DataTable();` line and the table sort is working! But I'm still getting the `Cannot read property 'childNodes' of undefined` error which is causing other stuff to break. :( so strange. Going to keep working on this, but may just end up checking your answer, then writing a new one out – Leon Gaban Oct 14 '14 at 15:38
  • Another thing I notice is that code inside my controller gets run twice: `alert('hi'); $('#manage_users_table').DataTable();` I see 'Hi' pop up twice, wonder if that has any bearing on this... going to update the code in my question – Leon Gaban Oct 14 '14 at 15:44
  • 1
    Maybe some stuff in routing. Like here: http://stackoverflow.com/questions/15697011/angularjs-controller-executes-twice – omakoleg Oct 15 '14 at 13:18
  • Yeah thanks! That solved the Controller code running twice. I think I need to remake this question. The problem is that when the template code gets loaded in, it seems like something needs to reinitialize. No problems if I leave the datatables script tag inside the template html, only a problem if I try to move it into the controller where it belongs – Leon Gaban Oct 15 '14 at 14:52
  • I'm able to use dataTables inside of my controller now, despite still getting the error, going to check this answer :) Going to an Angular meetup tonight, will try and get that issue ironed out once and for all. – Leon Gaban Oct 16 '14 at 15:03
1

The solution is simple

You are trying $('#manage_users_table').DataTable(); before the data is bind to the table. Try the same after data get binded. It works fine for me

jithin john
  • 552
  • 4
  • 12
0

I came across this recently but realised what I'd done. You can avoid this problem by making use of the native setTimeout, or the AngularJS equivalent $timeout.

Below is an example of the $timeout implementation.

var myApp = angular.module('myApp', []);
app.controller('ManageUsersController', function($scope, $timeout) {

  //Executes when Angular has finished loading.
  $timeout(function() {
    $('#manage_users_table').DataTable();
  });
});
Dan Atkinson
  • 11,391
  • 14
  • 81
  • 114