Closed professorjoshua closed 7 years ago
I thought about this an as an interim solution, try adding *ngIf='areColumnsInitialized' and then
areColumnsInitialized: boolean = false;
changeColumns(newColumns) {
this.areColumnsInitialized = false;
this.columns = newColumns;
this.areColumnsInitialized = true;
}
The idea being that the grid is briefly destroyed and recreated when you change columns. I suspect that is your issue so you wouldn't have to wait on all the rows.
Great minds think alike, however, I already tried that to no avail. In my code I used a Boolean called scrollbarV. I tried to change the scrollbarV property to true and false. I also tried the *ngIf based on the Boolean. The setting to false and true were placed around the assignment of columns.
<ngx-datatable *ngIf="scrollbarV==true" #myTable style="height:400px;"
[rows]="datarows"
[columnMode]="'standard'"
[columns]="columnproperties"
class='material expandable'
[selected]="selected"
[selectionType]="'single'"
[messages]="messages"
(activate)="onActivate($event)"
(select)='onSelectItem($event)'
[loadingIndicator]="loadingIndicator"
[scrollbarV]="scrollbarV"
[rowHeight]="50"
id="lookupdata">
</ngx-datatable>
Try to add setTimeout(() => window.dispatchEvent(new Event('resize'))); after new set is selected.
Tried setTimeout(() => window.dispatchEvent(new Event('resize'))); after the new set of data is selected but I still have the same problem. It appears the ngx-datatable is stuck in the position I scrolled to from the previous dataset. I even tried to use scrollTop() but have not had any success.
I have the same issue, when I go to another page (the same component is going ) I see white space .
<ngx-datatable
#table
class="material"
[rows]="rows"
[columns]="columns"
[selected]="selected"
[selectionType]="'multi'"
[columnMode]="'force'"
[headerHeight]="24"
[footerHeight]="0"
[rowHeight]="40"
[scrollbarV]="true"
[scrollbarH]="false"
[messages]="{emptyMessage: 'No items have been added to the collection'}"
(select)='onSelect($event)'
(page)='onPage($event)'
(recalculate)=recalculate($event) >
<ng-template #editTmpl let-value="value" let-row="row" let-i="index" >
<span title="Double click to edit"
*ngIf="!editing[row.$$index + '-name']">
{{value}}
</span>
<input #input autofocus type="text"
(blur)="updateValue($event, 'name', value, row, input)"
(keyup.enter)="updateValue($event, 'name', value, row, input)"
[hidden]="!editing[row.$$index + '-name']"
[value]="value"
[class.error]="row.error"
/>
<img class="rename-icon" src="assets/images/rename.png"
(click)="onRename( input, row )"
[hidden]="!checkingPermission(row, 'Update')" />
<!-- editing[row.$$index + '-name'] = true-->
</ng-template>
<ng-template #dateTmpl let-value="value" let-row="row" let-i="index">
<time>{{value | dateFormat }}</time>
</ng-template>
<ng-template #boolTmpl let-value="value" let-row="row" let-column="column" let-i="index">
<img class="validStatus-img" src="./assets/images/{{value?column.trueImg:column.falseImg}}" />
<span>{{value ? "Valid" : "Invalid"}}</span>
</ng-template>
</ngx-datatable>
-- Angular 4 -- ngx datatable 8.0.0
I've encountered this bug. I thought it was related to Angular change detection, because when I focused a md-input-container, suddenly ngx-datatable displayed. I tried manually calling markForChanges()
in a timeout, but it didn't work.
I think it may be related to this visibility directive thing:
https://github.com/swimlane/ngx-datatable/blob/908f1216818efe9c8c6322243070eed3cd7479ea/src/directives/visibility.directive.ts
I had another scrolling issue, which I fixed by manually scrolling datatableBody
, but I think it could work as a hack to fix this issue.
Setup
@ViewChild(DatatableComponent)
dataTable: DatatableComponent;
private datatableBodyElement: Element;
ngAfterViewInit(): void {
this.datatableBodyElement = this.dataTable.element.querySelector('datatable-body');
}
Scroll
this.datatableBodyElement.scrollTop = offsetY;
So maybe if you scrolled 1px back and forth it would display the table?
@arlowhite Thank you for the suggestion, however, it didn't work for me. I tried @ipassynk proposed solution too but I'm still stuck.
@professorjoshua did you scroll after a timeout (setTimeout)? maybe scroll back and forth 1px?
If all else fails, maybe force change detection first with markForCheck()
, then after 1ms timeout scroll 1px.
If none of that works, it must be related to ngx-datatable's VisibilityDirective, but I don't know much about it.
The same thing happens to me, I want to use the same table for multiple data and columns...
I believe this is caused by the same bug as #843. Basically, the rows are rendered in the latter scenario but they retain the scroll offset from before so they are rendered below the container. Scrolling then recalculates those rows positions so they appear in the viewport.
I have had to abandon the use of ngx-datatable, given the many problems and bugs I have encountered. I think that the vitualScroll would have to rethink, since in HTML the problem is not the displacement, if not the deferred creation of the rows. You can move a table element with more than 10000 rows and it will be faster than the virtualScroll with 100 rows
I have also had to abandon the use of the ngx-datatable. Sorry.
After a lot of attempted work-arounds, I've found something that worked for my project.
For me this bug was manifesting when the user had scrolled beyond the viewport, and we changed the rows array (shifting categories in my case). The new recordset would always appear blank if it was short, or it would be invisible until scrolling for longer recordsets. The code previously reset the rows to being empty while waiting on the service like this:
this.table.rows = [];
In my case, adding a simple object with a single column property in it was enough:
this.table.rows = [{name: ""}];
We ran into the same thing as @brokenhands clearing the results before the next set, and confirming the workaround also works! The only downside is if you have the row count display shown it does count it as a single row in the interim.
Finally found a hack for this:
http.get(...).subscribe(res => {
/// set rows
setTimeout(function() { $('datatable-body').scrollTop(1); }, 1);
setTimeout(function() { $('datatable-body').scrollTop(0); }, 1);
}
a solution with a timer .. better step ....
@rodrigoEclipsa could you please demonstrate? Could you show how have you solved it please
It's working for me now, after adding this source code:
setTimeout(() => { this.myGrid.element.getElementsByTagName('datatable-body')[0].scrollTop++; }, 1);
I solved this this way, following the idea of @markanthonyg , but I did this implementation using directives and listening to the input of rows , that when it is empty there will be no horizontal scroll so I save the last scroll and when there is data again I apply this routine, but I decided to hide with 'opacity' the element because in the meantime he made the screen dance dance , and this was a problem for me
Directive.
import { Directive, ElementRef, HostListener, Input, OnChanges } from '@angular/core';
@Directive({
selector: '[tableScroll]',
})
export class TableScrollDirective implements OnChanges {
private lastScrollLeft: number = 0;
@Input() rows = [];
constructor(private eleRef: ElementRef) {}
async ngOnChanges() {
let tableBody = this.eleRef.nativeElement.children.item(0).querySelector(".datatable-body");
if(this.rows.length === 0) {
this.lastScrollLeft = tableBody?.scrollLeft || 0;
} else {
tableBody.style.opacity = 0;
tableBody.scroll({
left: (this.lastScrollLeft - 1) || 0
});
await new Promise(resolve => setTimeout(resolve));
tableBody.scroll({
left: (this.lastScrollLeft + 1) || 0
})
tableBody.style.opacity = 1;
}
}
}
HTML
<ngx-datatable
tableScroll <-------------------------------------- **directive**
[scrollbarV]="true"
[scrollbarH]="true"
[messages]="{
emptyMessage: loading
? 'loading...'
: 'no documents !'
}"
class="ngx-border material expandable"
[ngClass]="{
'ngx-table-height-item': alreadyHadRow,
'ngx-table-height-item-small': !alreadyHadRow
}"
[count]="page.totalElements"
[externalPaging]="false"
[rows]="rows"
columnMode="standard"
[headerHeight]="50"
[footerHeight]="50"
[rowHeight]="32"
[limit]="page.size"
[selected]="selected"
(activate)="onActivate($event)"
(select)="onSelect($event)"
(sort)="onSort($event)"
[externalSorting]="true"
>
....
</ngx-datatable>
A way I solved this issue was as so:
this.rows.push(undefined); setTimeout(() => { this.rows = this.rows.filter((row) => row); }, 1);
Basically will force a re-render of the table. Will also work if a given list becomes smaller which results in a blank screen.
It seems that if we remove some rows and scroll bar disappears, the data table element does not reset the scrollPos values itself. So I ended up adding something like this in my datatable component which uses ngx-data-table:
@Input() set data(value: any[]) {
this.rows = value;
setTimeout(() => {
// here we reset scrollPos values on each data change if there is no scroller present.
if (!this.dataTable.bodyComponent.scroller) {
this.dataTable.bodyComponent.onBodyScroll({
scrollYPos: 0,
scrollXPos: 0
});
}
}, 0);
}
[ x ] bug report => search github for a similar issue or PR before submitting [ ] feature request [ ] support request => Please do not submit support request here
Current behavior
Create a drop down list that allows a user to select an object (a different table from the database to display). When the user selects the object change the column headings, call the API to retrieve the appropriate data. Up until now everything works. Even if one object has 10 rows and a second object has 1000 rows. Now set the vertical scroll to true (to increase the performance). Switching between objects still works partially. If you select the object with 1000 items, scroll towards the bottom of the table and then select the object with less rows you will see that the table is not repainted unless you scroll. You may have to resize the browser window to get a scroll bar.
Expected behavior
When you change the columns and rows (by selecting a different object) then table should be repainted regardless of where you were scrolled to in the previous table.
Reproduction of the problem
What is the motivation / use case for changing the behavior?
The vertical scroll is needed to increase the performance. Displaying the table of a 1100 rows of 5 columns took 6 to 10 seconds (depending on the browser) without the vertical scroll. With the vertical scroll the table was rendered in 1 second.
Please tell us about your environment:
Windows 10 Enterprise, Visual Studio 2015, IIS
Table version: 0.7.x
"@swimlane/ngx-datatable": "~6.3.0"
Angular version: 2.0.x
Angular 2
Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]
All browsers
Language: [all | TypeScript X.X | ES6/7 | ES5] TypeScript