3

can someone help me with rowCallback. Problem is, I have a table, and you can click anywhere on table row for open info for clicked item. On first TD I set check box. But when I check checkbox, I don't want to open info. Here is image for better explanation enter image description here

my code

var vm = this;
    vm.selected = {};
    vm.selectAll = false;
    vm.toggleAll = toggleAll;
    vm.toggleOne = toggleOne;

    var titleHtml = '<input type="checkbox" ng-model="showCase.selectAll" ng-click="showCase.toggleAll(showCase.selectAll, showCase.selected)">';


    function getUserTokenFromLocalStorage(localStorage) {
        var authData = [];
        for (key in localStorage) {
            if (key == "ls.authorizationData") {
                authData = localStorage[key];
            }

        }

        var jsonObj = JSON.parse(authData);
        return jsonObj.token;
    };


    var vm = this;
    vm.message = '';
    vm.someClickHandler = someClickHandler;
    vm.dtOptions = DTOptionsBuilder.newOptions()
        .withOption('ajax', {
            // Either you specify the AjaxDataProp here
            // dataSrc: 'data',
            url: serviceBase + 'test',
            type: 'POST',
            headers: {
                'xtoken': 'Bearer ' + getUserTokenFromLocalStorage(localStorage)
            }
        })
        // or here
        .withDataProp('data')
        .withOption('processing', true)
        .withOption('serverSide', true)
        .withOption('rowCallback', rowCallback)
        .withOption('createdRow', function(row, data, dataIndex) {
            // Recompiling so we can bind Angular directive to the DT
            $compile(angular.element(row).contents())($scope);
        })
        .withOption('headerCallback', function(header) {
            if (!vm.headerCompiled) {
                // Use this headerCompiled field to only compile header once
                vm.headerCompiled = true;
                $compile(angular.element(header).contents())($scope);
            }
        })
        .withPaginationType('full_numbers')


    vm.dtColumns = vm.dtColumns = [
        DTColumnBuilder.newColumn(null).withTitle(titleHtml).notSortable()
        .renderWith(function(data, type, full, meta) {
            vm.selected[full.id] = false;
            return '<input type="checkbox" ng-model="showCase.selected[' + data.id + ']" ng-click="showCase.toggleOne(showCase.selected)">';
        }), //don't change state when click on this TD, only check checkbox.
        DTColumnBuilder.newColumn('id').withTitle('ID'),
        DTColumnBuilder.newColumn('type').withTitle('Type'),
        DTColumnBuilder.newColumn('city').withTitle('City'),
        DTColumnBuilder.newColumn('country').withTitle('Country'),
        DTColumnBuilder.newColumn('last_report_dt').withTitle('Last report'),
        DTColumnBuilder.newColumn('hardware_version').withTitle('HW version'),
        DTColumnBuilder.newColumn('rpi_image_version').withTitle('Image version'),
        DTColumnBuilder.newColumn('software_version').withTitle('Code version'),
        DTColumnBuilder.newColumn('internal_note').withTitle('Internal note'),
        DTColumnBuilder.newColumn(null).withTitle('Info').notSortable()
        .renderWith(function(data, type, full, meta) {
            vm.selected[full.id] = false;
            return '<a class="btn btn-default" ng-href="info/' + data.id + '">Info</a>';
        }),
    ];

    function toggleAll(selectAll, selectedItems) {
        for (var id in selectedItems) {
            if (selectedItems.hasOwnProperty(id)) {
                selectedItems[id] = selectAll;
            }
        }
    }

    function toggleOne(selectedItems) {
        for (var id in selectedItems) {
            if (selectedItems.hasOwnProperty(id)) {
                if (!selectedItems[id]) {
                    vm.selectAll = false;
                    return;
                }
            }
        }
        vm.selectAll = true;
    }


    function someClickHandler(info) {
        vm.message = info.id;
        $location.path('info/' + info.id);

    }

    function rowCallback(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
        // Unbind first in order to avoid any duplicate handler (see https://github.com/l-lin/angular-datatables/issues/87)
        $('td', nRow).unbind('click');
        $('td', nRow).bind('click', function() {
            $scope.$apply(function() {
                vm.someClickHandler(aData);
            });
        });
        return nRow;
    }


}

1 Answer 1

3

Have had this issue myself. I think your approach is a little bit backwards. You declare the td click handler inside rowCallback, just to be able to pass the id. Instead I will recommend this :

  1. Add a no-click class to the first column to prevent click :

    DTColumnBuilder.newColumn(null).withTitle(titleHtml).notSortable()
      .withClass('no-click')
      .renderWith(function(data, type, full, meta) {
         vm.selected[full.id] = false;
         return '<input type="checkbox" ng-model="showCase.selected[' + data.id + ']" ng-click="showCase.toggleOne(showCase.selected)">';
       }), 
    
  2. Change the rowCallback to do nothing but injecting the id as attribute to the row :

    function rowCallback(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
       $(nRow).attr('data-id', aData.id);
    }
    
  3. Create a delegated event handler on the td's to replace both the event handler inside rowCallback and your someClickHandler() :

    $('#tableid').on('click', 'tbody td:not(.no-click)', function() {
      var id = $(this).parent().attr('data-id');
      vm.message = id;
      $location.path('info/' + id);
    })
    
Sign up to request clarification or add additional context in comments.

Comments

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.