1

I am using angular-datatables plugin to add datatables to my project. In this, I have a column Actions where I want to add some buttons. For this, I am using ng-template which is defined on the same page. The problem is that the template does not always render. It sometimes shows the button, and sometimes it does not. It never shows the buttons after I make a search.

controller

$scope.dtOptions = DTOptionsBuilder.newOptions().withOption('ajax', {
        url: '/api/department',
        type: 'GET'
    })
    .withDataProp('data')
    .withOption('processing', true)
    .withOption('serverSide', true)
    .withPaginationType('full_numbers')
    .withOption('createdRow', function (row, data, dataIndex) {
        // Recompiling so we can bind Angular directive to the DT
        $compile(angular.element(row).contents())($scope);
    })
    .withBootstrap();
$scope.dtColumns = [
    DTColumnBuilder.newColumn('id').withTitle('ID'),
    DTColumnBuilder.newColumn('name').withTitle('Name'),
    DTColumnBuilder.newColumn('actions').withTitle('Actions').withOption("searchable", false)
];

view

<script type="text/ng-template" id="actions.html">
     <button class="btn btn-primary btn-xs" ng-click="edit()"><i class="fa fa-edit"></i> Edit</button>
     <button class="btn btn-danger btn-xs" ng-click="delete()"><i class="fa fa-trash"></i> Delete</button>
</script>
<div class="hbox hbox-auto-xs hbox-auto-sm" ng-controller="DepartmentsController">
    <div class="bg-light lter b-b wrapper-md">
        <h1 class="m-n font-thin h3">Departments</h1>
    </div>
    <div class="wrapper-md">
        <div class="panel panel-default">
            <div class="panel-body">
                <div class="row">
                    <div class="col-xs-6">
                        <button class="btn m-b-md btn-md btn-primary " ui-sref="manager.departments.create">
                            <i class="fa fa-plus"></i> <span class="hidden-sm hidden-xs">Add Department</span></button>
                    </div>
                </div>
                <div class="row">
                    <div class="col-sm-12 m-b-xs">
                        <table datatable="" dt-options="dtOptions" dt-columns="dtColumns" class="table table-striped b-t b-b">
                            <thead>
                                <tr>
                                    <th style="width:20%">ID</th>
                                    <th style="width:60%">Name</th>
                                    <th style="width:20%">Actions</th>
                                </tr>
                            </thead>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

controller on server side in Laravel

public function index() {
    $departments = Department::company($this->company->id)
            ->select("departments.id", "departments.name");

    return \Datatables::of($departments)
            ->add_column("actions", function($row) {
                return '<div ng-include src="\'actions.html\'"></div>';
            })
            ->make(true);
}

I belive this is some syncronization issue. But, I am not getting anywhere.

1 Answer 1

1

Do you really get any successfully inserted templates? The only way I can get $compile(angular.element(row).contents())($scope) to work is when the <table> is prebuilt or rendered by ng-repeat.

Here delayed injected HTML from a jQuery AJAX needs to be replaced with a ng-template including bindings, I think $scope.$apply() is the only way around :

.withOption('createdRow', function (row, data, dataIndex) {
   $scope.$apply($compile(angular.element(row).contents())($scope))
 })

Works for me -> http://plnkr.co/edit/UqZKhpgMx7aHCXdaNkiN?p=preview


Silly me. The same can be done in a simple $timeout.

$timeout(function() {
   $compile(angular.element(row).contents())($scope)
})

http://plnkr.co/edit/5OTeHHUgkIurd6Z3DCkP?p=preview

Sign up to request clarification or add additional context in comments.

4 Comments

it worked. thanks!! does $scope.$apply cause any performance problems?
@ShashankJain, you are welcome, thank you for accepting the answer. But I was a kind of silly. See update. A $timeout should be enough. After all, all we want is to be sure the $compile is performed in a digest later on.. But to answer your question - no, I do not believe a single $apply after the dataTable is initialised should cause performance problems at all. Mutiple $apply triggered over and over is very bad.
but, here $scope.$apply is getting called when each row is created. So, if there are say 50 rows in the table, this will get called 50 times.
@ShashankJain, yes, but only once. It is dataTables that is responsible for rendering the <table> (no ng-repeat), so $compile must be executed on dataTables internal nodes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.