问题
Using Angular v2.4.8 and PrimeNg v1.1.4
I have a page with two components:
- Dropzone, for uploading files
- p-datatable to show the uploaded files
I configured Dropzone to send 5 files at a time and when it is finished with 5 files the event onDropZoneSendingMultiple
is raised. When all files are uploaded onDropZoneQueueComplete
is raised.
In both listeners I want to refresh the datatable which is in the second component. This is not working. I need to refresh the page to see the new files.
My HTML of the main page:
<div class="row" id="dropzoneContainer">
<dropzone class="dropzone" #dz [config]="dropZoneConfig"
(error)="onDropZoneUploadError($event)"
(sendingmultiple)="onDropZoneSendingMultiple($event)"
(queuecomplete)="onDropZoneQueueComplete($event, dz);"
(maxfilesreached)="onDropZoneMaxfilesReached($event)"
(maxfilesexceeded)="onDropZoneMaxfilesExceeded"></dropzone>
</div>
<div class="row">
<div class="col-md-12">
<FilesList></FilesList>
</div>
</div>
The Dropzone
-component shows the dropzone. The FilesList
shows the datatable.
Part of the HTML:
<p-dataTable [hidden]="loading" [value]="files" selectionMode="single" (onRowSelect)="details($event)">
In my main ts-file I have:
@ViewChild(FilesListComponent)
public filesListComponent: FilesListComponent;
private reloadFileList() {
this.filesListComponent.reload();
}
In my filelist ts I have
public files: File[];
public reload() {
this.getFiles();
}
public getFiles() {
this.fileService.getAll()
.then(
data => {
this.files = data;
});
}
getFiles
is also called at page load.
When I add console.log()
statements I can see getFiles()
is called and this.files
is updated, but the table doesn't refresh.
回答1:
For anyone still looking for the new syntax of adding records to an array that is bound to a primeng table
this.arrayRecords= [...this.arrayRecords, newObject];
回答2:
Update: PrimeNG recently removed the DoCheck interface which was automatically detecting changes, see: https://www.primefaces.org/primeng-4-0-0-rc4-released/
The answer is to use the spread operator( [...arr] - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator ) to add items to your array instead of .push().
Original Answer: I had a similar issue which I solved using a slightly different approach. If you are using the same service to upload and retrieve your files you can use RxJS instead of listening to events across components.
On my services I want to reload across the app when I make a POST or PUT I use:
private _shouldUpdateSource = new BehaviorSubject<boolean>(false);
shouldUpdateObservable = this._shouldUpdateSource.asObservable();
In your POST and/or PUT methods
this.http.post(..).map( res => {this._shouldUpdateSource.next(true);});
Which allows you to subscribe to the fileService.shouldUpdateObservable in your components:
this.shouldUpdateSub = this.fileService.shouldUpdateObservable
.subscribe((shouldUpdate: boolean) => {
if (shouldUpdate) {
this.updateFiles();
}
});
This seems to be the best way to handle communication about a service between components I've seen/used.
-Edit-
Here is the same concept in the official documentation:
https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service
-Edit 2- I ran into this issue again after updating to 4.0.0. FWIW, I ended up removing the PrimeNG Datatable, instead using a manual *ngFor and it worked fine. It seems that the PrimeNg documentation( https://www.primefaces.org/primeng/#/datatable ) tells you to:
"For example, use slice instead of splice when removing an item or use spread operator instead of push method when adding an item."
I'm not sure why they ask you to do this because it is contrary to what the official Angular documentation tells you to do but I believe it has something to do with why the [value] binding not working as you would expect.
Personally, I am moving away from PrimeNg in favor of the Covalent data table which has an explicit refresh() function: https://teradata.github.io/covalent/#/components/data-table
回答3:
UPDATE:
I took a better look at the documentation for p-dataTable, particularly the section titled Change Detection. I removed the [immutable]=false
attribute work-around in the p-dataTable
tag and instead I'm now getting the table to refresh by returning something like this when I modify the underlying array:
return myOriginalArray.slice();
ORIGINAL:
I was having trouble with getting p-datatable
to update/refresh when I removed an item from the underlying array used to populate the table. No clue as to why, but adding the following attribute to the p-datatable
tag fixed things for me:
[immutable]=false
I'm using PrimeNG ^4.1.3
回答4:
I suspect this has to do with how your child component is handling changes. You should implement the onChange event and set the files that way. Here is an example:
```
export class FilesListComponent implements OnChanges {
@Input() files: File[];
ngOnInit() {
}
// Subscribe to the change event and update the model
ngOnChanges(changes: {[propName: string]: SimpleChange}) {
let key = 'files';
this.files = changes[key].currentValue;
}
}
```
回答5:
We can mark the view for check and call detechchange.
@ViewChild('searchDt') searchTable: DataTable;
self.dealService.getAccounts(self.searchParams).subscribe((response) => {
Deal.setAvailableAccount(response.map((current) => {
return {
"cifNumber": current['cif'],
"ucic": current['ucic'],
"accountNomenclature": current['customerName'],
}
}));
**self.searchTable.changeDetector.markForCheck();
self.searchTable.changeDetector.detectChanges();**
});
来源:https://stackoverflow.com/questions/42587424/primeng-datatable-doesnt-refresh