3

I'm trying to select only the rows from an ng-table with filtered data. Using the following code filters the table rows but even the rows that aren't shown are being selected:

controller:

let sampleData = [{id: 1, name: 'John Doe', gender: 'Male'},
    {id: 2, name: 'Jane Doe', gender: 'Female'},
    {id: 3, name: 'Mary Jane', gender: 'Female'},
    {id: 4, name: 'Mary Poppins', gender: 'Female'}];

$scope.tableParams = new NgTableParams({

}, {
    dataset: sampleData
});

$scope.checkboxes = {
    checked: false,
    items: {}
};

$scope.$watch(() => {
    return $scope.checkboxes.checked;
}, (value) => {
    sampleData.map((item) => {
        $scope.checkboxes.items.id = value;
    });
});

$scope.$watch(() => {
    return $scope.checkboxes.items;
}, () => {
    let checked = 0;
    let unchecked = 0;
    let total = sampleData.length;

    sampleData.map((item) => {
        if ($scope.checkboxes.items.id) {
            checked++;
        } else {
            unchecked++;
        }
    });

    if (unchecked === 0 || checked === 0) {
        $scope.checkboxes.checked = checked === total;
    }

    angular.element($element[0].getElementsByClassName('select-all')).prop('indeterminate', (checked != 0 && unchecked != 0));
});

html:

<script type="text/ng-template" id="checkbox.html">
    <input type="checkbox" ng-model="checkboxes.checked" class="select-all" value="">
</script>
<table class="table" ng-table="tableParams" show-filter="true">
    <tr ng-repeat="item in $data track by $index">
        <td header="'checkbox.html'">
            <input type="checkbox" ng-model="checkboxes.items[item.id]">
        </td>
        <td data-title="'Name'" filter="{'name': 'text'}">
            {{item.name}}
        </td>
        <td data-title="'Gender'" filter="{'gender': 'text'}">
            {{item.gender}}
        </td>
    </tr>
</table>

When the table is filtered via name or gender, the table rerenders with the filtered data. When you click on the select all checkbox while the table is filtered, the filtered rows are selected. Unfortunately, when you clear the filter, the previously filtered out rows are also selected. The same is true when selecting all the filtered rows and then triggering an action that's supposed to get the selected items. (All ids are selected for the action.)

How can I only select the filtered rows? Thank you.

dork
  • 4,396
  • 2
  • 28
  • 56

2 Answers2

1

Okay, I got it to work. I just added a tableData object to the $scope so I can store the filtered data there. That's what I used for checking the selected items.

let sampleData = [{id: 1, name: 'John Doe', gender: 'Male'},
    {id: 2, name: 'Jane Doe', gender: 'Female'},
    {id: 3, name: 'Mary Jane', gender: 'Female'},
    {id: 4, name: 'Mary Poppins', gender: 'Female'}];

$scope.tableData = {
    filteredData: [],
    checkboxes: {
        checked: false,
        items: {}
    }
};

$scope.tableParams = new NgTableParams({
    page: 1,
    count: 10
}, {
    total: data.length;
    getData: ($defer, params) => {
        let filter = params.filter();
        let count = params.count();
        let page = params.page();
        let filteredData = filter ? $filter('filter')(data, filter) : data;

        params.total(filteredData.length);
        $scope.tableData.filteredData = filteredData;

        $defer.resolve(filteredData.slice((page - 1) * count, page * count));
    }
});

$scope.$watch(() => {
    return $scope.tableData.checkboxes.checked;
}, (value) => {
    $scope.tableData.filteredData.map((item) => {
        $scope.tableData.checkboxes.items[item].id = value;
    });
});

$scope.$watch(() => {
    return $scope.tableData.checkboxes.items;
}, () => {
    let checked = 0;
    let unchecked = 0;
    let data = $scope.tableData.filteredData;
    let total = data.length;
    let checkboxes = $scope.tableData.checkboxes;

    data.map((item) => {
        if (checkboxes.items[item].id) {
            checked++;
        } else {
            unchecked++;
        }
    });

    if (unchecked === 0 || checked === 0) {
        checkboxes.checked = checked === total;
    }

    angular.element($element[0].getElementsByClassName('select-all')).prop('indeterminate', (checked != 0 && unchecked != 0));
});

Not really sure if this is the best way to go about it. Also, this doesn't change the select all checkbox's state to indeterminate when you filter > select all > clear filter.

dork
  • 4,396
  • 2
  • 28
  • 56
0

in your second watch, change to return $scope.tableData.filteredData; may solve your problem