Ng-table: tableParams.reload() does not reload filter data

Created on 27 Jan 2014  ·  30Comments  ·  Source: esvit/ng-table

i'm using tableParams.reload() (and params.total(filteredData.length)) which reloads the table with the new external data, but the selections in "select" and "select-multiple" filters do not change. tableParams.reload() should call the "filter-data" functions again, no? is there another way to accomplish this?

Most helpful comment

My data is loaded successfully on DOM but when i fetch the data from server and want to refresh the ng-table by tableParams.reload() its not reflecting the result, but when i click on sorting or paging then its reflecting the result.
what issue can be this?

All 30 comments

Hi there. First of all - thanks for the project.
I have the same problem. I need to update filters with data fetched from a server, but have no idea how to trigger filter-data func.

I found that if you declare your data right within the getData function it seems to update the table.
So..... getData: function($defer, params){
var data = $scope.yourdata;
var orderedData = ...............................
}

My data is loaded successfully on DOM but when i fetch the data from server and want to refresh the ng-table by tableParams.reload() its not reflecting the result, but when i click on sorting or paging then its reflecting the result.
what issue can be this?

I'd like to second what @basilcronus suggested, this also worked for me. Would love to know what the reason for this is.

Had the same issue with @developersatish.
Wait for a resolution to this problem.

Hi everyone. I just recently started using ngTable. Im having a similar issue especially with nested ngTables and reloading data separate to the parent data. here is a quick idea:

parent controller:

var parentData = [...];

$scope.details = -1

$scope.showDetails = function (id) {
$scope.details = id;
};

// ngTable ////////
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 10, // count per page
sorting: {
id: 'asc' // initial sorting
}
}, {
total: parentData.length, // length of data
getData: function($defer, params) {
// use build-in angular filter
var orderedData = params.sorting() ?
$filter('orderBy')(parentData, params.orderBy()) :
parentData;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});

on the html I have an ng-click to send the id to this and change the details scope.

Child controller (Secondary table that relates to the first controller):

var childData = [...];

$scope.$parent.$watch('details', function () {
console.log("you made it here");
$scope.tableParams2.reload();
});

// child ngTable ////////
$scope.tableParams2 = new ngTableParams({
page: 1, // show first page
count: 10, // count per page
sorting: {
id: 'asc' // initial sorting
}
}, {
total: childData.length, // length of data
getData: function($defer, params) {
// use build-in angular filter
var orderedData = params.sorting() ?
$filter('orderBy')(childData, params.orderBy()) :
childData;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
},
$scope: { $data: {} }
});

I can see the change when i click but my child table isn't updating. Not sure if this helps, but i do think it is related.

Hi,
I'm also having the same issues as @developersatish. The table data is only updated after I sort or filter the table. Is there any solution to this issue?

I have a similar issue.

On a click event I start retrieving data from a server (multiple calls).
So I have a for loop and in there I have GET requests and I store the results that return into a scope variable that I wanna plot in a table async.

However on click I instantiate my table as so:

`$scope.tableParams = new ngTableParams({
        page: 1, // show first page
        count: 10, // count per page
        sorting: {
            Country: 'asc' // initial sorting
        }
    }, {
        total: $scope.continentTableData.length, // length of data
        getData: function($defer, params) {
            for (var i = 0; i < numberOfCountries; i++) {
                try {
                    var country = $("path[class*=" + $scope.currentContinentCountries[i].toUpperCase() + "]")[0].__data__.properties.name;
                    MapService.getInfographicsData(2013, country, function(infrographicsData) {
                        counter++;
                        // debugger;
                        var cpi = infrographicsData[0].data.CPI;
                        var trace = infrographicsData[1].data;
                        var countryName;

                        if (cpi == null) {
                            countryName = trace.Ref_Country;
                        } else {
                            countryName = cpi.Country;
                        }

                        var joinedData = {
                            Country: countryName,
                            Cpi: cpi,
                            Trace: trace
                        }
                        $scope.continentData.push(joinedData);

                        $scope.continentTableData = $scope.continentData;

                        // if (counter==numberOfCountries-1) {
                        //     console.log("tier");
                            $timeout(function() {
                            // update table params
                            params.total($scope.continentTableData.length);
                            // set new data
                            console.log("new data set");
                            $defer.resolve($scope.continentTableData);
                        }, 1500);
                        // };

                    });
                } catch (e) {
                    // console.log(e);
                    continue;
                }                    
            }

            // $scope.$apply();
        }
    });`

as in the ngTable example with ajax. However nothing is shown in the table (getData never gets called.)

If I click "refresh" tableParams, Then the table starts loading everything except that each item is duplicated.

Any idea?

@developersatish I was able to reflect new data from the server by copying the functionality attached to the pagination buttons.

$scope.tableParams.count(1);

I placed this in the callback of my request.

myRequest().then(function(response) {
    $scope.data = response;
    $scope.tableParams.total($scope.data.length);
    $scope.tableParams.count(1);
});

Edit:

In my original post, the 1 in $scope.tableParams.count(1) should actually be replaced with a variable that contains the value set to count in ngTableParams.
See http://embed.plnkr.co/harWG3J6OlNHzbOu0e6S/preview for a working example.

Since this is the top search result for this problem, I'll include what i did for my solution. I simply stored in my $scope the array of {id,title} objects that is used as the argument to the defer.resolve in the filter-data function. (it could be / is probably empty initially.) You can then update that array at any time and the changes will be reflected in the filter select. So i update it when my ajax call brings back the server response.

Also in my case the table data set expands (is augmented) as the user expands the search range. This requires that I also modify (apply a diff to) the select filters.

I tried that but it doesn't work. Can you paste your working example?

Hey Guys,
I have the same issue as @almaplayera, i have a scenario something like

1. The filterdata used in dropdown is coming from service

2. And to update the same data i have a section from where user can add new entries/ update the existing.

3. After Adding/Updating the entries from add/edit section filterdata for dropdown that dropdown should be refreshed once the table is reloading.

I am doing this to get my company data to filter-data -

screen4ngtable

After that i called the getCompany Method in filter-data of my view -

screen5ngtable

Can anyone please suggest any solutions to get my filter-data updated with the recent data from service Or provide some examples for alike use case.

@esvit : i have tried to get my data at getData callback in ngTablePrams and binded it to $scope after that i tried passing the same variable to filter-data in view something like @israelidanny suggested in https://github.com/esvit/ng-table/pull/342 but that also is not working for me. :(

P.S : i am doing tableParams.reload(); after adding & editing.

I no longer have my code as I switched away from ng table before I committed anything. However, going from memory:

The filter functions (your getCompany function) are only invoked once on table init. So you have to apply changes to the resolved data array whenever there are record changes and angular will apply those changes to the dom.

$scope.company_filter = [];

$scope.getCompanyFilter = function(data) {
  var def = $q.defer();
  companyService.getAll().success(function(response) {
    $scope.updateCompanyFilter(response.data);
    def.resolve($scope.company_filter);
  });
  return def;
};

$scope.updateCompanyFilter = function(data) {
  $scope.company_filter.length = 0;
  for (i in data) {
    $scope.company_filter.push({
        'id': data[i].id,
        'title': data[i].name
    });
  }
};

// Then wherever you refresh your table data, just call updateCompanyFilter(data).
// Or you could micro manage the filter array when you do adds/deletes instead of reseeding it every time.

<td ... filter-data="getCompanyFilter($column)" >

Again, i could be wrong since it's been a few months.

Is this issue fixed in the latest version of ng-table?

Could somebody provide an example code

I don't think it is.

Now, I don't think it would be too difficult to make the
controller.loadFilterData function available to be called from the
tablParams. You would then be able to call this when the lists change in
your application.

C

On Fri, Jun 19, 2015 at 6:59 AM, rachithaShetty [email protected]
wrote:

Is this issue fixed in the latest version of ng-table?


Reply to this email directly or view it on GitHub
https://github.com/esvit/ng-table/issues/186#issuecomment-113384084.

:+1: @kyleboyle : your solution rocks buddy, it worked for me..! Awesomeness...! Thanks a lot.

It appears that the resolution to this issue (Pull request 403: https://github.com/esvit/ng-table/pull/403) was merged in v0.4.2, but the change that it made has since been reverted.

On line 549 of ng-table.js change

$scope.$watch('params.$params', function(newParams, oldParams) {
to
$scope.$watch('[params.$params, params.data]', function(newParams, oldParams) {

This resolved the issue with data being updated, but the table not refreshing to render the changes.
It appears that this bug was reintroduced in this commit: https://github.com/esvit/ng-table/commit/9189e987fba90b07ffc6b17c982961ad65edf725#diff-6aca4bc06732c0635eb9860dc6cd040fL490

Unfortunately $watch'ing params.data causes issues in certain circumstances:

when the elements within params.data are complex involving circular references, $watch'ing _by value_ causes a stack overflow exception when angular.copy creates a deep clone.

I believe a newer version of angular.copy fixes this particular issue, however its still a bad idea to watch params.data _by value_ for performance reasons.

@kyleboyle This code works perfectly! Thanks! And adding the inArray function can filter out the duplicates.

    $scope.manufacturer_filter = [];
    $scope.getManufactFilter = function(column){
        var def = $q.defer();
        ResourseAPI.query(function(data){
            $scope.updateManufactFilter(data.devices);
            def.resolve($scope.manufacturer_filter);
        });
        return def;
    };
    $scope.updateManufactFilter= function(data) {
        var arr = [];

        angular.forEach(data, function (item) {
            if (inArray(item.manufacturer, arr) === -1) {
                arr.push(item.manufacturer);
                $scope.manufacturer_filter.push({
                    'id': item.manufacturer,
                    'title': item.manufacturer
                });
            }
        });
    };

    var inArray = Array.prototype.indexOf ?
    function (val, arr) {
        return arr.indexOf(val);
    } :
    function (val, arr) {
        var i = arr.length;
        while (i--) {
            if (arr[i] === val) return i;
        }
        return -1;
    };

@kyleboyle Your solution is great.
Does anyone know if they could implement something similar but using ng-table-dynamic?
I load columns dynamically by javascript.

Example:

var column = {
    title: 'Example',
    sortable: 'example',
    filter: 'example',
        filterData: .....,
    show: true,
    field: 'example'
};

What should set property filterData? Or is there another way to reload data filters?

There are lots of different ways to specify the array that the select filter will use as a datasource. Each of these methods apply to both ng-table and ng-table-dynamic.

Maybe the following code sample can help you figure something out?

http://codepen.io/christianacca/pen/JdqjxB?editors=101

Good sample, but I can not find the solution to my problem. In all examples the data are loaded only once (sync or async) but they are not reloaded.

An example of what I get is:
I have two columns: Countries and cities, each one with a filter.
So:

  • When the country filter is null, prompted the server all cities.
  • When the country filter is selected, asking the server the only city that country applies and update the filterData of cities column.

It is understood? Sorry for my English.

Thanks for the reply.

@kyleboyle none of these solutions work for me (I'm not even doing any filtering) and I'm taking it as a sign of poor code quality that the table doesn't update when the underlying data does. What Angular table solution did you switch to?

@BartoGabriel I think what you're trying to do is possible. A guy I worked with solved the problem by creating his own filter template that did exactly what you said. He overrode the select.html template in a similar fashion to the following example: http://codepen.io/christianacca/pen/xGeWGX?editors=101

Sorry I can't be more helpful, just pushed for time!

Oh BTW, the guy I mentioned, he used the ui-select2

@christianacca thanks for your help. It was very useful.
When I have the solution I will share.

Cool :-)

Hi guys, is my solution totally wrong or is @kyleboyle's just a better alternative?

@telwing your solution didn't work for me, but then again, neither did @kyleboyle 's . I'm not actually doing any filtering, though. I'm just sorting data from an array, $scope.users. When I remove an element from that array and call reload() on the table parameters, nothing happens. It's really surprising that something like this is so complicated unless I'm missing something basic.

I'm also having the same issues as @developersatish.i also tried setting tableParams count but my getdata function call only at page load while filtering data by drop down list it is not able to call this function

$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 8, // count per page
sorting: {
LastSeen: 'desc' // initial sorting
},
filter: {
PatientName: '', // initial filter
},
}, {
filterSwitch: true,
getData: function ($defer, params) {
// use build-in angular filter
var filteredData = params.filter() ?
$filter('filter')($scope.items, params.filter()) :
$scope.items;

        var orderedData = params.sorting() ?
                            $filter('orderBy')(filteredData, params.orderBy()) : filteredData;
        params.total(orderedData.length); // set total for recalc pagination
        $scope.tableParams.count(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));

        $defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));



    }
});
Was this page helpful?
0 / 5 - 0 ratings

Related issues

esvit picture esvit  ·  37Comments

penchiang picture penchiang  ·  5Comments

faceleg picture faceleg  ·  11Comments

Ebolon picture Ebolon  ·  12Comments

raul1991 picture raul1991  ·  6Comments