I have a total of 250 items and I'm displaying 5 of them i.e. pageSize is set to 5.
and I've set the paginator.length property to items.length
Now, there are two problems here:
Even though I've manually set the paginator.length but when I console.log the properties of paginator, it shows 5 (Which is the number of items I'm displaying per page). hence the next button of paginator is disabled.
How do I enable the next button, so that when it is clicked I would know and request the next data to server.
Remember: I'm using only back-end pagination for this regard.
Pagination information is passed in response headers from the server.
Here is my code
pageIndex=1;
pageNumber;
pagination;
ngOnInit(): void {
this.paginator.pageSize = 5;
this.paginator.pageIndex = this.pageIndex;
this.salesReportService.getDailyReport().subscribe((response) => {
console.log('Response of sales report : ', response);
this.reports = response.body;
this.pagination=response.headers.get('X-Pagination');
console.log('PaginationInformation: ',this.pagination)
this.paginator.length=this.pagination.TotalCount;
console.log('paginator properties: ', this.paginator);
console.log('paginator hasNextpage(): ', this.paginator.hasNextPage());
this.dataSource = new MatTableDataSource(this.reports);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}, (error) => {
console.log('Error occured while fetching sales report: ', error);
});
}
// here I'd call the function to get the next data when the next button of paginator is clicked.
// something like this
this.salesReportService.getReports(pageNumber:2)
This is because you set paginator length in the first place and later trying to execute below lines
this.dataSource = new MatTableDataSource(this.reports);
this.dataSource.paginator = this.paginator;
which makes paginator to set length to data available in datasource.
So, after the above two lines keep the below line in your code.
this.paginator.length=this.pagination.TotalCount; // this.paginator.length= 'No Of Records';
Hope it helps!
Related
I'm making the pagination of a web that shows data updated every 2 minutes from an API (the API is paginated but I need to do my own pagination to show the data as I want, example: 100 elements per page, page number 5, that would show elements from 401 to 500).
private readonly _start = new Subject<void>();
private readonly _stop = new Subject<void>();
lista : any = [];
pNum = 1;
act = timer(0, 120000);
constructor(private ListaService:ListaService) {
this.act.subscribe(() => {
this.ListaService.getLista(this.pNum,'usd').pipe(
takeUntil(this._stop),
repeatWhen(() => this._start)
).subscribe(resp=>{
this.lista = resp
});
})
}
start(): void {
document.body.scrollTop = 0;
this._start.next();
}
stop(): void {
this._stop.next();
}
So the thing is, when I click the button to change the page, the methods stop() and start() are called, and also the variable pNum is updated with the number of the page selected. I thought that doing this would load the data of the page selected but it's not happening, the data updates 2 minutes after I click the page number when the timer triggers.
Is there any way to manually refresh the timer and update the parameters of the observable?
Yes, modify your act to include a source for "manual" updates, thus:
manual$ = new Subject<void>();
act = merge(timer(0, 120000), this.manual$)
Then whenever you need a manual update, call next on manual$ thus:
this.manual$.next();
EDIT
While we're at it, don't nest subscribe calls - use a flattening operator (switchMap is suitable in this case), thus:
this.act
.pipe(switchMap(_ => this.ListaService.getLista(this.pNum,'usd')))
.subscribe(resp => this.lista = resp);
See stackblitz for demo.
I'm trying to write a fetch to get data from an api. The data within the network tab shows the correct data that I want to update to my html, but the data that ends up there is always the previously returned data currently.
For example, I load the page with quantity selected = 1, the price per item returns properly as 2.25, when I switch to 6, the expected price per item returned is 2.14 (discount taken care of in another script) this is the price shown in the network tab. Unfortunately this isn't the price that gets updated into my html span. it will still show the 2.25 until I make another selection, then it will update to the 2.14. This is the problem, my html always seems to be loading the previously calls result. Any help would be greatly appreciated. Thankyou!
<script>
var span = document.getElementById("price-span");
//Call to cart API
async function start() {
const headers = new Headers();
headers.append('pragma', 'no-cache');
headers.append('cache-control', 'no-cache');
await fetch('/cart.js', {
method: 'GET' , headers: headers
})
.then(promise => promise.json())
.then(data => render(data))
}
//Helper Functions
async function render(data) {
span.textContent = "$" + insertDecimal(data.items[0].discounted_price) + " CAD";
console.log(data.items[0].discounted_price)
}
function insertDecimal(num) {
return Number((num / 100).toFixed(2));
}
</script>
Note: The total price functions properly and was written previously by someone else
picture for ref
how the start is called
Created a simple react-admin application that pulls from a custom rest api. First page is displayed (default 10 per page. Click the Next button and nothing happens (still sends page=1 to the api). Click a second time and the page advances to page 2 (page=2), as expected. Click the third time and goes back to page 1 (page=1).
Then, if you click a fourth time, it goes page 2, then click again, goes to page 3, then click again, goes back to page 1. It continues with this pattern, each round, getting one page further before going back to page.
I'm able to get the correct results when calling the custom API outside of the react-admin app. I created a custom dataProvider to communicate with the API and maybe there's a problem with the getList function, but I can definitely see the page number passed into this function and it lines up with the odd results (page 1, then 1, 2, 1, then 1, 2, 3, 1, etc. The custom API expects the following query string for pagination: ?limit=10&page=1&orderBy=id&orderDir=ASC
The original react-admin tutorial returns 10 records. When I set the page limit to 5, it does seem to work OK (advances to page 2 on the first click of Next), but without more records, it's hard to test it completely. But my guess is it would work, since it is most certainly a problem with my code or the API (although, as I said, the API works outside the react app).
Here's my getList function:
const httpClient = (url, options = {}) => {
if (!options.headers) {
options.headers = new Headers({ Accept: 'application/json' });
}
const tokens = localStorage.getItem('tokens');
const objToken = JSON.parse(tokens);
options.user = {
authenticated: true,
token: `Bearer ${objToken.accessToken}`
};
return fetchUtils.fetchJson(url, options);
};
export default {
getList: (resource, params) => {
const { page, perPage } = params.pagination;
const { field, order } = params.sort;
const { q } = params.filter;
// Pagination and sort
let query = `limit=${perPage}&page=${page}&orderBy=${field}&orderDir=${order}`;
// Filter?
let useResource = '';
let useFilter = '';
if (q == null) {
// No filter: Use <resource>/ url
useResource = resource;
} else {
// Filter: Use append url with /find
useResource = `${resource}/find`;
useFilter = q;
console.log('useFilter: ', useFilter)
query += `&searchText=${useFilter}`;
}
const url = `${apiUrl}/${useResource}?${query}`;
return httpClient(url)
.then(({ json }) => ({
data: json.results,
total: json.totalRows,
}));
}, ...
Here's a screen shot of issue:
EDIT:
It looks like the correct query string is being sent but immediately after the first Next page click (page=2), page=1 is automatically sent again, returning to page one. This seems to be the case with subsequent Next clicks, as well. Thanks for helping out a newbie. But I just can't figure out why extra calls are being made returning to page 1.
Fixed in react-admin 3.4.3.
I updated using npm update and pagination works correctly.
I have exactly behavor with react 4.x.x
What i was expecting:
Going to next page when cliking on next, with react-admin 3.19 this is how my application worked
What happened instead:
when you click on the next page, pagination resets to 1 !
also, it does not take into account the pagination that I define.
on chrome default perPage is 5, even when i set it 10.
chrome_pagination_issue
on firefox default perPage=10, but i have the same issue
firefox_pagination_issue
Other information:
getList: (resource, params) => {
const { page, perPage } = params.pagination;
const { field, order } = params.sort;
console.log(params);
const query = {
...fetchUtils.flattenObject(params.filter),
_sort: field,
_order: order,
_start: (page - 1) * perPage,
_end: page * perPage,
_resource:resource
};
const url = `${apiUrl}/${resource}?${stringify(query)}`;
return httpClient(url).then(({ headers, json }) => {
if (!json.hasOwnProperty('totalElements')) {
throw new Error(
"The numberOfElements property must be must be present in the Json response"
);
}
return {
data: json.content,
total: parseInt(json.totalElements,10)
};
});
}
#4658
Environment
React-admin version: 4.0.1 , 4.0.2
React version:18
Strict mode disabled
Browser: chrome, firefox
My backend is spring boot rest api
So I have this problem. I can't get out more results than the one that's typed inside of the method. There is a table with different rows when clicking on a row routing takes u to a detail page about that certain page. Now the problem is I only get the selected one.
[0] is the only result I get..
ngOnInit() {
this.route.paramMap.subscribe((params: ParamMap) => {
this.service.getData().subscribe((world: any) => {
this.country = world.Country.filter(
(country: Country) => country.Code = params.get('code'))[0];
});
});
}
I have a jqGrid that points at an external API, which I have no control over. This external API has two endpoints:
Data Endpoint - Returns the table row data
Count Endpoint - Returns pagination counts etc.,
Based on user input the jqGrid filter gets converted into the appropriate query-string to filter the external API's Data and Count Endpoints.
I have jqGrids url being dynamically built based off of user input and targets the Data Endpoint...and during the loadBeforeSend() event it calls the Count Endpoint to get the latest pagination information based on users filter.
I am using the jsonreader capabilities:
jsonReader: {
root: 'products',
id: 'id',
records: function () {
return gridTotal;
},
total: function () {
// var totalPages = (gridTotal + reqOptions.limit-1) / reqOptions.limit;
var totalPages = Math.ceil(gridTotal / reqOptions.limit);
console.log('totalPages: ' + totalPages);
return totalPages;
},
page: function () {
//var totalPages = Math.ceil(gridTotal/20);
console.log('currentPage: ' + reqOptions.page);
return reqOptions.page;
}
},
Sample of the loadBeforeSend method:
loadBeforeSend: function (xhr, settings) {
settings.url = _newUrl || endpointURL;
// Lets fetch our data count...this may change as items get published so lets fetch during load
products.count(accessToken, _filterQuery)
.success(function (resp) {
// This is the total number of products that match our current search
gridTotal = resp.count;
}).catch(function (err) {
console.error(err);
});
}
Fetching from the Data Endpoint works really well, the issue is how to call the Count Endpoint and update the pagination data.
Tried the following:
Using setGridParam for records, last_page, etc.,
Using getGridParam('reccount')
Just update the html to look correct (not effective since paging will be off)
Is there a way to
Manually fire off the XHR for jqgrid URL...so I can request the Count first and when it returns then go fetch the Data?
Rerun the jsonreader functionality once the Count returns and gridTotal is set
Use a promise like structure to resolve records count
Updated to show #Oleg solution
loadBeforeSend: function (xhr, settings) {
settings.url = _newUrl || endpointURL;
// Lets fetch our data count...this may change as items get published so lets fetch during load
products.count(accessToken, _filterQuery)
.success(function (resp) {
// This is the total number of products that match our current search
gridTotal = resp.count;
gridTotal = resp.count;
grid.jqGrid('setGridParam', {
page: gridOpts.jsonReader.page(),
records: gridTotal,
lastpage: gridOpts.jsonReader.total()
});
grid[0].updatepager(false, true);
}).catch(function (err) {
console.error(err);
});
}
I hope that I correctly understand your problem. In the case you can first make loading of the main data from the Data Endpoint. Then (inside of loadComplete) you can start new $.ajax request manually to get the data from the Count Endpoint and to update the pagination data inside of success callback of the $.ajax.
What you need to do for the updating the pager is:
setting of page, records and lastpage parameters of jqGrid based on the data returned from the Count Endpoint.
call of $("#grid")[0].updatepager(false, true); which will uses the above options and to refresh the information on the pager.
You can see in the old answer and example of usage of .updatepager(false, true).