Hi,
We have a CRUD application, user selects data to edit from a PrimeNG datatable. Datatable uses pagination. Datatable is reset on add/edit to clear filters, sorting etc.
Lets say, user selects a record on page number 5 and edits the same. After edit when datatable is rendered again then pagination is reset to page number 1.
We need to set the page number as per selected record but not able to find any method on DataTable Component to perform the same.
Please look into this.
Hello!
My solution (load datatable state):
`component template: component ts:
export class ......{
@ViewChild('dataTable') public dataTable: DataTable;
ngOnInit(){
let storedEvent: LazyLoadEvent = states[0].value.event;
this.dataTable['first'] = storedEvent.first; // this private, :(
this.dataTable.rows = storedEvent.rows;
this.dataTable.sortField = storedEvent.sortField;
this.dataTable.sortOrder = storedEvent.sortOrder;
this.dataTable.multiSortMeta = storedEvent.multiSortMeta;`
We also wanted to do this, and are working around it by getting the datatable as a ViewChild and then forcing the paginator to set the page we want (see below):
@ViewChild(DataTable) dataTable: DataTable;
... and
setCurrentPage(n: number) {
let paging = {
first: ((n - 1) * this.dataTable.rows),
rows: this.dataTable.rows
};
this.dataTable.paginate(paging);
}
Hm, I have tried the workaround, the page seems to be set correctly (at least console.log tells me so), but the table isn't re-rendered it seems... only if I click my "Update"-Button in the browser. But if I try to set the page in ngOnInit() programmatically, it just stays on the first page.
The background of my problem is that the table always starts with page 1, even if I am on e.g. page 3, I click on a row which takes me to a different view/component to see the row data details and if I navigate back to the list the page is lost and I am at the start again ... :(
Here is my code:
// template
<p-dataTable #dt ...
// component
@ViewChild('dt') dataTable: DataTable;
ngOnInit() {
this.getData();
}
getData() {
this.difflogService.getLogsUrl().then(
difflogs => {
this.difflogs = difflogs;
// test - set the table to a fix paging value to
// see if it works ...
this.setCurrentPage(2);
},
error => {this.addAlert(<any>error, "danger");}
);
}
onPage(event) {
console.log("paging occured ...");
console.log(event);
}
setCurrentPage(n: number) {
let paging = {
first: ((n - 1) * this.dataTable.rows),
rows: this.dataTable.rows
};
this.dataTable.paginate(paging);
}
And I see that the event is triggered and that the first element should be 10 ... but it still is 0
Hm, weird, the above code works if I call "this.datatable.reset()" first:
setCurrentPage(n: number) {
// only works if reset is called first...?
this.dataTable.reset();
let paging = {
first: ((n - 1) * this.dataTable.rows),
rows: this.dataTable.rows
};
this.dataTable.paginate(paging);
}
Not sure about that call to reset, I haven't had to do that anywhere.
In my case, I get the required page e.g "2" from an optional route parameter
ngOnInit() {
this.gridPage = (this.route.snapshot.params['page'] || 1); // Get the page we want, if no parameter then default to the first page
}
Then after the component is loaded, I set the current page.
ngAfterViewInit() {
this.dataTable.setCurrentPage(this.gridPage);
}
I've tried to set it in the ngAfterViewInit() callback, too, but that didn't help either...
My guess now is that maybe you are using server side pagination whereas I am using client side pagination? I am setting/getting the current page via a service, that part works well btw.
I'm doing client side paging too mate.
Not sure what else could be the difference .. we are loading our data via a service in ngOnInit(), then setting the page in ngAfterViewInit().
The other thing we do is capture the selected page size e.g 5, 10 or 20, in a user preferences service and apply that to all grids as the default page size by binding to the datatable rows property. That rows value also gets used in our setCurrentPage function.
Anyways it's working or both of us :thumbsup:
Hm, true, the paging is working, but the sorting isn't ... :( If I get back on the datatable view, the page is set now, but the sorting info is lost... I am setting the sort field and order via a custom object (the values are ok), but that doesn't work... any idea? Can you post your sorting and rows part, too? What version are you using? I have even updated all my package.json libs (Angular 2.3.0, primeng 1.0.0, ...), didn't help either ...
/**
* Set datatable page from outside
* @param n
*/
setCurrentPage(n: number) {
// only works if reset is called first...?
this.dataTable.reset();
let meta = this.difflogService.getCurrentDatatableMeta();
if (typeof meta !== "undefined" && meta.currentRows > 0) {
console.log("setting sorting and rows ...");
console.log(meta);
this.dataTable.sortField = meta.sortField;
this.dataTable.sortOrder = meta.sortOrder;
this.dataTable.multiSortMeta = meta.multiSortMeta;
this.dataTable.rows = meta.currentRows;
//this.dataTable['first'] = meta.currentPage;
}
let paging = {
first: ((n - 1) * this.dataTable.rows),
rows: this.dataTable.rows
};
this.dataTable.paginate(paging);
}
I'm using packages: Angular ~2.1.0 and PrimeNg 1.0.0-rc.7
We're not setting the sort field and order ... but I just had a quick try for single sort and it's working for me e.g. for a table that has a DataColumn for field 'LoginId'
setCurrentPage(n: number) {
let paging = {
first: ((n - 1) * this.dataTable.rows),
rows: this.dataTable.rows
};
this.dataTable.paginate(paging);
this.dataTable.sortField = "LoginId";
this.dataTable.sortOrder = -1;
}
Not sure why you need to set this.dataTable.rows ? The call to paginate will do that.
Why ?
this.dataTable.paginate(paging); this start method !!! after setting lost ...
before call paginate or start lazy load, settings all filter , sorter other ....
primeng datatable.ts (https://github.com/primefaces/primeng/blob/master/components/datatable/datatable.ts)
paginate(event) {
this.first = event.first;
this.rows = event.rows;
if(this.lazy) {
this.stopFilterPropagation = true;
this.onLazyLoad.emit(this.createLazyLoadMetadata());
}
else {
this.updateDataToRender(this.filteredValue||this.value);
}
this.onPage.emit({
first: this.first,
rows: this.rows
});
}
Hi,
Using Angular 2.2.4 and PrimeNG 1.1.1, I tryed something like @garthmason 's code,
If I try to store current page and rowsPerPage it works.
If after that I fill in sort data in my dataTable like the code below, dataTable does not go to current page despite of _paginate_ method receives the right parameters in _ngAfterViewInit_.
RowsPerPage is kept correctly.
this.dataTable.sortField = sortField;
this.dataTable.sortOrder = sortOrder;
I wanted to leave a quick thank you here to @garthmason. Your setCurrentPage code works served as a great basis for the work-around I ended up implementing in our project.
I will also say, for @smxsm's benefit, that I do have single column sorting preserved and working. The only differences I can see between the code you both have above is that I am setting the field and order on the datatable immediately before calling paginate. I also am not calling dataTable.reset().
Hope that helps, and thanks again for the great comments and help.
It turned out that I had to call reset() because we were setting the initial sorting in the template ... and I think it may be by design that if you set some sorting, the datatable is going back to page 1, so it might not even be a bug :)
Anyways, I ended up using a little timeout to go to the correct page after sorting the data.
So here is my final setCurrentPage() method:
setCurrentPage() {
let n = 1;
let meta = this.difflogService.getCurrentDatatableMeta();
if (typeof meta !== "undefined") {
n = meta.currentPage;
if (typeof meta.sortField !== "undefined") {
this.dataTable.sortField = meta.sortField;
this.dataTable.sortOrder = meta.sortOrder;
}
this.dataTable.rows = meta.currentRows;
}
if (n > 1) {
let paging = {
first: ((n - 1) * this.dataTable.rows),
rows: this.dataTable.rows
};
// the problem is that if we set sorting, the table is
// always going back to page 1, so we set a timer to go
// back to the current page ...
let timer = Observable.timer(100);
timer.subscribe(t=> {
this.dataTable.paginate(paging)
});
}
}
Thanks for the help, all :)
@smxsm
That _timer_ was the key to make it work!
While DataTable does not provide a better way to keep pagination data, I'll try to learn how to extend a component to make it reusable.
Thank you all.
Hello @smxsm and @darioribas . I think I noticed the multiple calls to load the data as you did. On my project, since it was utilizing lazy loading, it would call to load data from within the ngOnInit, which I was specifying, and then it would call it again on the sort due to having an initial column set for sorting. In order to bypass that, and have the original load invoked, which was pulling the values for the last used sort field and sort order, I simply ensure that during initialization, that load call performs a no-op, and only after that will it handle it's calls. This is done with a simple initialization flag. I don't need to call reset in this case.
I would guess that is probably why you are seeing your timer work. You are waiting long enough until after that load that is triggered by the initial table sort fires, and then you fire the paginate call. It would be interesting to find out if that is the case, however. Glad you found a solution that works, and let me know if you are seeing the same behavior that I was seeing.
Thanks!
Ugh...of course, my posting that has since resulted in what was working, failing.
@smxsm you are definitely correct in that there is some kind of timing element involved. I merged in some other changes, and realized that there had been a small delay already in the flow that I was investigating. When I removed that, it threw things off and I had to incorporate some timing in order to make it work correctly again. Interestingly enough, I don't have to call reset(), I don't delay the pagination call either. Neither of those items worked. What I had to do was in my loadData function, the initial two calls, the first by the table itself initializing, and the second as a result of the pagination call, I've delayed by 100ms each.
I don't believe this is really robust, and I fear that other changes may break it again, but I hope this will be stable enough until a better solution is put in place.
I would also like to note that during the pagination, it doesn't seem to correctly update the rowIndex values. I had a column that was computing it's display based of the rowIndex, and it definitely computes it from the initial load, with the initial sort column and initial data rows.
When the pagination occurs, it then correctly sorts them, but if any of those rows had already been computed in terms of their data with respect to the initial rowIndex, it will retain that value. Only rows that were not loaded by the initial load, and thus have not had their value computed yet, will correctly display based off the newly sorted rowIndex values.
Has anyone else seen this or noticed this? Or is this simply another oddity that may be timing related?
Thanks all in advance.
Using first property should enable this. For example if you set it to 0, datatable should page to first page. Please drop a comment if that doesn't work for you and we may reopen.
I am still not able to make it work after following the above fix. I do see that there is an example mentioned in the doc as well on how to do it.
https://www.primefaces.org/primeng/#/datatable
Still no luck.
Created a plunkr to reproduce the same. Here it is.
https://plnkr.co/edit/QMjg7AXpirlYbevtRORK?p=preview
I am using primeng 2.0.1
This issue should be reopened. @vaibhavcodegeek are you able to make it work?
Hi,
I am using primeng 4.1.0-rc.2 but "first" property still does not work.
regards,
Carlos
Just for documentation. 'first' does work with PrimeNg Turbotable (Version 5.2.0).
I have a solution does work for now.
@ViewChild('dataTable') public dataTable: any;
setCurrentPage(n,e) {
// debugger;
let paging = {
first: ((n - 1) * this.dataTable.rows),
rows: this.dataTable.rows
};
this.dataTable.paginate(paging);
this.dataTable.first=0;
// this.dataTable.changePageToFirst(e);
}
let e = { first: 0 };
this.projectList=[];
this.loadListingFromParent(e);
setTimeout(()=>this.setCurrentPage(0,e),1000);
Most helpful comment
We also wanted to do this, and are working around it by getting the datatable as a ViewChild and then forcing the paginator to set the page we want (see below):
@ViewChild(DataTable) dataTable: DataTable;... and