简体   繁体   中英

How to access current row data in angular-datatables using templates?

I am using angular-datatables . There is a column Actions which I render using an inline template. I want to access current row data in that template. How do that?

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) {
        return $timeout(function() {
            // Recompiling so we can bind Angular directive to the DT
            return $scope.$apply($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

<div class="hbox hbox-auto-xs hbox-auto-sm" ng-controller="DepartmentsController">
    <!-- Inline Template -->
    <script type="text/ng-template" id="actions.html">
         <button class="btn btn-primary btn-xs" 
              ng-click="edit(/** CURRENT ROW ELEMENT ID */)"><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="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>

Here is plunkr to help you: http://plnkr.co/edit/iAZBof7g6cp68RnM0X8H?p=preview

After hours of struggle, I found the solution. It's quite obvious when you see it.

I created a new scope and added data to it before passing it to $compile in createRow callback. Creating a new scope is necessary to pass unique data to each row. If you simply passed by $scope.row then each row will have the same row equal to the last row processed.

controller

.withOption('createdRow', function (row, data, dataIndex) {
       // Create a new scope for each row, otherwise, data will
       // not be unique for each row becuase of data bindings
       var $newScope = $scope.$new(true);
       $newScope.row = data;

       // Pass any methods you are using in current scope
       $newScope.delete = $scope.delete;

       return $timeout(function() {
                // Recompiling so we can bind Angular directive to the DT
                return $scope.$apply($compile(angular.element(row).contents())($newScope));
            });
        });

view

<script type="text/ng-template" id="actions.html">
    <button class="btn btn-primary btn-xs" ui-sref="manager.departments.edit({id: {{ row.id }} } )"><i class="fa fa-edit"></i> Edit</button>
    <button class="btn btn-danger btn-xs" ng-bootbox-confirm="Are you sure you want to delete this department?" ng-bootbox-confirm-action="delete(row.id)"><i class="fa fa-trash"></i> Delete</button>
</script>

I used the above accepted answer , and it worked fine. However, later when we moved to production and the rows per page changed from 20 to 500 , I saw significant performance issues through chrome developer tools (Most time spent on hundreds of setTimer and listener events)

I found the official document here which gives us an example as below:

.withOption('createdRow', createdRow);

// ...

function createdRow(row, data, dataIndex) {
    // Recompiling so we can bind Angular directive to the DT
    $compile(angular.element(row).contents())($scope);
}

This piece of code does not use the $timeout or $apply functions, but still works well. If you run into performance issues as I did, this may help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM