I have 2 functions to load data: when init page and search page.
When init page, the data display with 5 pages. I click page 3, the data show with paging is Ok. After that, enter data search. The data table is reload, but the page number does not reset to 1, it's still page 3.
in html:
<p-paginator rows="5" totalRecords="{{totalRecords}}" (onLazyLoad)="paginate($event)"
(onPageChange)="paginate($event)" [rowsPerPageOptions]="[2,5,10,20]"></p-paginator>
ts:
defaultPage:0;
defaultSize:2
paginate(event) {
let currentPage: number;
this.defaultPage = event.first / event.rows;
this.defaultSize = event.rows;
this.listData = [];
if (this.isSearch == 1) {
this.getLoadPageSearch(this.defaultSize, this.defaultPage);
} else {
this.getLoadPage(this.defaultSize, this.defaultPage);
}
}
Please adivice me how to reset the paginator after call another API
The p-paginator component contains the changePageToFirst function. To access this function, we will need to obtain a ViewChild reference to the component. For example, in our template we define the component:
<p-paginator rows="10" totalRecords="100" #p></p-paginator>
<button (click)="reset($event)">Reset</button>
And in our component, we can handle the reset event as follows:
#ViewChild('p', {static: false}) paginator: Paginator;
reset($event) {
this.paginator.changePageToFirst($event);
}
Here is a demo: https://plnkr.co/edit/FxwTHK0W2WuTCjuqhLp6?p=preview
EDIT: The above demo is no longer working on plunkr. Here is an updated version:
https://stackblitz.com/edit/angular-u9nqf5
Another useful method is changePage.
In template:
<p-paginator #pp></p-paginator>
In the component:
#ViewChild('pp') paginator: Paginator;
this.paginator.changePage(0);
For those using the dataTable primeng component and using its lazy pagination feature,
we can reset the page to '1' by using
this.tableTemplateName.first = 0;
where setting first=0 means first page
Related
I am trying to set an array to a state hook. Basically I want to keep a track of a per-row (of grid sort of) Edit Dialog Open State. Basically per row, I have a Edit button, launches a . As all seems rendered initially, I am trying to manage the show hide by keeping an array in the parent grid component. When user clicks on the Edit button, per row, I want to pass the rowData as props.data and want to provide the Edit functionality.
To keep the state of the editDialogs (show/hide), I am making a array of objects useState hook as follows:
const [editDialogsModalState, setEditDialogsModalState] = useState([{}]); // every edit dialog has it's own state
...
function initializeEditDialogsModalState(dataSet) {
let newState = [];
dataSet.map((item) => newState.push({ id: item.id, state: false }));
return setEditDialogsModalState(newState); // **PROBLEM->Not setting**
}
function addUDButtons(currentRowDataMovie) { // my edit/delete button UI code
const currRowDataId = currentRowDataMovie.id;
return (
<span>
<button
type="button"
className="btn btn-info"
onClick={() => setEditDialogsState(currRowDataId)}
>
Edit
</button>
{editDialogsModalState[currRowDataId].state && ( // **PROBLEM->null data even after set call**
<EditMovieComponent
open={editDialogsModalState[currRowDataId].state}
onToggle={toggleEditDialogsModalState(currentRowDataMovie)}
movie={currentRowDataMovie}
/>
)}
}
......
function buildGrid() {
{
if (!ready) {
// data is not there, why to build the grid
return;
}
initializeEditDialogsModalState(movies);
...........
}
However not able to get the editStates. A screen shot from debugger where I can see the movies (REST output), ready, but not the editDialogsModalState state array.
In general, is there a better ways of implementing such per-row basis functionality where on click of a button I want to open a React-bootstrap and pass the row-specific dataitem for doing operations ? (I am learning React, so may not not yet fully aware of all pointers).
Thanks,
Pradip
I am trying to pass data to a single modal instance and reuse it multiple times inside a loop. It is working but whenever I'm clicking over an image, I'm getting an error - You may have an infinite update loop in a component render function.
This is the html where I'm looping over an array of images and passing it to a modal instance.
<li v-for="(source, i) in sources()" :key="i+'K'">
<span v-b-modal.fancybox #click="fancyBox(source)">
<p>click me</p>
</span>
</li>
This is the html for bootstrap-vue modal -
<b-modal
id="fancybox"
:modal-class="myclass"
hide-footer
centered
>
<img class="fancybox" :src="resource">
</b-modal>
Following is the vue js code -
export default {
data: () => ({
myclass: ['myclass'],
srcItems: [],
resource: ''
}),
methods: {
sources () {
this.srcItems = [
'https://picsum.photos/id/0/5616/3744',
'https://picsum.photos/id/1/5616/3744',
'https://picsum.photos/id/10/2500/1667',
'https://picsum.photos/id/100/2500/1656',
'https://picsum.photos/id/1000/5626/3635'
]
return this.srcItems
},
fancyBox (source) {
this.resource = source
}
}
}
I couldn't able to figure out what is wrong here! Please help me. Thank you for your time.
Hope this will help you to get started
**[LIVE DEMO](https://codepen.io/boussadjra/pen/xxERwZm)**
I have a mat-table that might show up to 5/10/15 entries per page. At first, I had one mat-paginator at the bottom that worked fine. Now I'm being asked to set a paginator at the top and another one at the bottom of the table, so the user won't have to scroll all the way down to reach the paginator if they are looking for an entry that is at the top.
I tried to link both paginator to the same data source. But it didn't worked. So, tried to create 2 datasource, but it also has one limitation.
The only limitation is that the paginator at the bottom can't change items per page, since there isn't a method that lets me control that property.
Also, I couldn't set the page index or items per page properties directly (the table was not refreshing), so all the movements are achieved with some logic and paginator methods like previousPage() or lastPage().
Can anyone help me with this? I'm fine with the solution with either single or multiple datasource.
Working code -> STACKBLITZ
<mat-paginator #paginatorTop (page)="pageEvent = handlePageTop($event)" [length]="length" [pageSizeOptions]="[5, 10, 15]" showFirstLastButtons></mat-paginator>
<mat-paginator #paginatorBottom (page)="pageEvent = handlePageBottom($event)" [length]="length" [pageSizeOptions]="[5, 10, 15]" showFirstLastButtons></mat-paginator>
app.component.ts
ngOnInit() {
this.dataSource2.paginator = this.bottomPaginator;
this.dataSource.paginator = this.topPaginator;
this.topPaginator.length = this.dataSource.data.length;
this.bottomPaginator.length = this.dataSource2.data.length;
}
public handlePageTop(e: any) {
let {pageSize} = e;
this.bottomPaginator.pageSize = pageSize;
if(!this.topPaginator.hasNextPage()){
this.bottomPaginator.lastPage();
}else if(!this.topPaginator.hasPreviousPage()){
this.bottomPaginator.firstPage();
}else{
if(this.topPaginator.pageIndex < this.bottomPaginator.pageIndex){
this.bottomPaginator.previousPage();
} else if(this.topPaginator.pageIndex >this.bottomPaginator.pageIndex){
this.bottomPaginator.nextPage();
}
}
}
public handlePageBottom(e: any) {
if(!this.bottomPaginator.hasNextPage()){
this.topPaginator.lastPage();
}else if(!this.bottomPaginator.hasPreviousPage()){
this.topPaginator.firstPage();
}else{
if(this.bottomPaginator.pageIndex < this.topPaginator.pageIndex){
this.topPaginator.previousPage();
} else if(this.bottomPaginator.pageIndex > this.topPaginator.pageIndex){
this.topPaginator.nextPage();
}
}
}
No need to use two paginators made some changes in your code, please check it.
Here is my stackblitz code :- https://stackblitz.com/edit/multiple-paginators-svwwfj
Hope this helps!
This solution works if you want to show one paginator at a time
To solve the above problem, I created a directive scroll-to. In this directive i listened for scroll events and compared the window.pageYOffset with element's nativeElement.offsetTop
if (pageYOffset of window < element's offsetTop) im was setting the property showUpperOne true else property showLowerOne true.
import {Directive,HostListener,ElementRef} from '#angular/core'
#Directive(
{
selector:"[scrolledTo]",
exportAs:"scrolledTo"
}
)
export class ScrollDirective {
showUpperOne=true;
showLowerOne=false;
constructor(private el:ElementRef){}
#HostListener("window:scroll",['$event'])
onScroll(){
const elementPosition = this.el.nativeElement.offsetTop;
const scrollPosition = window.pageYOffset;
this.showUpperOne=scrollPosition<elementPosition
this.showLowerOne = scrollPosition>= elementPosition;
}
}
I used this directive on div which contains two paginators having the same template reference and one mat table
<div #mainDiv="scrolledTo" scrolledTo class="example-container mat-elevation-z8">
<mat-paginator *ngIf="mainDiv.showUpperOne" #paginator
[pageSize]="currentPageSize"
[pageSizeOptions]="[5, 10, 20]"
(page)="pageEvents($event)"
[showFirstLastButtons]="true">
</mat-paginator>
<mat-table #table [dataSource]="dataSource">...
</mat-table>
<mat-paginator *ngIf="mainDiv.showLowerOne" #paginator
[pageSize]="currentPageSize"
[pageSizeOptions]="[5, 10, 20]"
(page)="pageEvents($event)"
[showFirstLastButtons]="true">
</mat-paginator>
I did set the template reference variable for div #mainDiv="scrolledTo"
and accessed the properties of directive to show and hide paginators *ngIf="mainDiv.showLowerOne" , *ngIf="mainDiv.showUpperOne" respectively.
This will show or hide the paginators on scroll but there will be problem with giving the paginator functionality to other paginator once one paginator hides. It has to be set to datasource again.
In order to solve this,i added currentPageSize property and did set the default value as
10 currentPageSize=10;. In order to reassign the paginator to datasource, i listened for the page events using (page)="pageEvents($event)" in template of paginator.
and in pageEvents function
pageEvents(event){
this.currentPageSize=event.pageSize;
}
also on scroll
#HostListener("window:scroll",['$event'])
onScroll(){
setTimeout(()=> this.dataSource.paginator = this.paginator,0)
}
Stackblitz: https://stackblitz.com/edit/angular-nbtcgz
I want to load ag-grid inside a button click. I have tried two approaches but none is working
My code : First Method
onBtnClick(){
this.gridOptions ={
onGridReady : function(){
console.log("print");
}
}
}
Second method:
onBtnClick(){
this.onGridReady();
}
onGridReady(){
this.gridApi = params.api;
console.log("print");
}
First method not working. Second method says api is not defined
You can have this approach.
Have a flag in your component when to display the grid.
Use this flag to conditionally display the grid using *ngIf
Set this flag value on button click
This way, the template having ag-grid won't be rendered until the flag is set. When it's set, the template will be rendered and onGridReady will be called.
<button (click)="btnClick()">Display grid</button>
<ag-grid-angular *ngIf="displayGrid"
#agGrid
......
></ag-grid-angular>
btnClick(){
this.displayGrid = true;
}
Check this working example: ag-grid display on button click
Have you checked if ag-gridis connected to onGridReady?
It should look something like that:
<ag-grid-angular
...
(gridReady)="onGridReady($event)"
>
</ag-grid-angular>
You should share more of you code, it's unclear what you are doing.
You must make sure your gridOptions are fully set up BEFORE the grid initializes. (Doing this on a button is too late)
ngOnInit(): void {
this.gridOptions.onGridReady = gridReadyHandler;
}
gridReadyHandler = (params: GridReadyEvent) => {
this.gridApi = params.api;
console.log("grid is done loading", this.gridApi);
}
In my Angular2 application there are two components for form view and graph view. In the form, there is a spinner and checkbox for auto refresh handle.
Form Component html
<div class="refresh-spinner">
<my-checkbox
[selected]=autoRefresh
[disabled]="false"
[id]="'autoRefresh'"
[name]="'Auto Refresh Every'"
[code]="'autoRefresh'"
(status)="checkAutoRefresh($event)">
</my-checkbox>
<my-spinner [title]="''"
[category]="'duration'"
[maxCount]=maxRefreshTime
[minCount]=minRefreshTime
[value]=minRefreshTime //default refresh value is 1 min
[editable]="true"
(count)="getAutoRefreshInterval($event)">
</my-spinner>
<span class="post__text"> Mins</span>
</div>
Form Component ts
// form view emits selected criteria
#Output() criteria = new EventEmitter<any>();
checkAutoRefresh(ele) {
this.autoRefresh = ele.selected;
localStorage.setItem('autoRefresh', ele.selected);
}
getAutoRefreshInterval(interval) {
localStorage.setItem('refreshInterval', interval.value);
}
Refresh interval and checkbox value (autoRefresh true/fasle) are set is local storage on spinner event and checkbox select event.
Graph components ts
alive: boolean; // used to unsubscribe from the IntervalObservable when OnDestroy is called.
#Input() criteria: FilteringCriteria;
constructor(private element: ElementRef, private myService: MyService) {
this.alive = true;
}
ngOnInit() {
let interval: number = JSON.parse(localStorage.getItem('refreshInterval'));
console.log(Date());
this.getStatistics();
IntervalObservable.create(interval * 60 * 1000)
.takeWhile(() => this.alive)
.subscribe((e) => {
// console.log(e)
if (JSON.parse(localStorage.getItem('autoRefresh'))) {
console.log(Date());
this.getStatistics();
}
});
}
ngOnDestroy() {
this.alive = false;
}
These form view and graph view are used in main component as below.
<search-criteria (criteria)="emitCriteria($event)"></search-criteria> //filteringCriteria emits from here
<ng-template ngFor let-result [ngForOf]="servers" let-i="index">
<my-grid-item row [class]="'graph--view'"
[colspan]="4">
<graph-view [criteria]="filteringCriteria"></graph-view>
</my-grid-item>
</ng-template>
Two Questions:
1. Once I check auto refresh checkbox graphs are refresh in 1 minute. But time interval is calculating from the time component is initialized not from the time the checkbox is selected.
2 If I change the value of the spinner (from 1 min to 2 min) local storage value is changed to new value 2. But graphs are refreshing in 1 min time intervals. But if I hit on form done button, then the graphs are refreshing in new time interval(2 min).
Any suggestions are appreciated.
Thank You!
It is happening because you are initializing the Observable as part of the init process of the graph component. So the time is taken from the moment it is initialized and when you update the interval it does not know about that and keeps using the one with which it was initialized.
You can declare a variable to hold the subscription and move all your code to subscribe to a different method. Something like
subscription;
constructor(private element: ElementRef, private myService: MyService) {
}
ngOnInit() {
this.getThreadPoolStatistics();
this.autoUpdateInit();
// subscribe to autoRefresh and interval changes
// autoRefreshChange.subscribe( () => this.autoUpdateInit());
// intervalChange.subscribe( () => this.autoUpdateInit());
}
autoUpdateInit(){
let interval: number = JSON.parse(localStorage.getItem('refreshInterval'));
console.log(Date());
// remove the old subscription
if(subscription) {
subscription.unsubscribe();
subscription = null;
}
// create one only when you need it. check for autorefresh and alive?
if(<subscription required>){
subscription = IntervalObservable.create(interval * 60 * 1000)
.subscribe((e) => {
// console.log(e)
if (JSON.parse(localStorage.getItem('autoRefresh'))) {
console.log(Date());
this.getStatistics();
}
});
}
}
You have to make sure, your Graph component gets the updates to the autorefresh and interval and call the autoUpdateInit again to make sure it updates the IntervalObservable. You can use a service to make sure both the components are looking at the same values as per this answer. If they are having a parent-child relation, then you can emit the changes via the #Output.