i'm new in Angular since a week i'm facing an anoying issue that i'cant fix it. After uploading a file in my backend to insert users from a compagny, my MatTable doesn't refresh automatically by itself, I need to reload the page to see users has been added. I've search actually almost everything about this topic but none of them helped me. I have two components (fileUpload and listUser rendered in same route). Even when i'm calling my getUsers() rest api method , nothing change. By advance thank's for the helps and sharing knowledge.
UserService.ts
export class UserService {
public refreshList$ = new BehaviorSubject<boolean>(true);
constructor(private http: HttpClient) {}
getUsers(): Observable<IUsers[]> {
return this.http
.get<IUsers[]>(`${BASEURL}/list`)
.pipe(
map((users) => {
console.log(users);
return users;
})
);
}
uploadFile(file: File): Observable<HttpEvent<any>> {
const formData: FormData = new FormData();
formData.append('file', file);
return this.http
.post<HttpEvent<any>>(`${BASEURLL}/upload`, formData, {
reportProgress: true,
responseType: 'json'
});
}
FileUploadComponent.ts
export class FileUploadComponent {
@Output() emitUpload : EventEmitter<BehaviorSubject<boolean>> = new EventEmitter();
constructor(private user: UserService) { }
upload(): void {
// ignore upload file process..
this.user.refreshList$.next(false); // try to notify upload has been done to call getList()
this.emitUpload.emit(this.user.refreshList$); // FileUploadComponent.ts is a child of my listComponent.ts
}
}
ListUserComponent
export class ListUserComponent implements OnInit{
displayedColumns: string[] = ['username', 'lastName', 'firstName'];
users : IUsers[];
usersDataSource: MatTableDataSource<IUsers>;
@ViewChild(MatPaginator) paginator !: MatPaginator;
constructor(private user: UserService) { }
ngOnInit() {
this.getUserList(); // get my users when component is rendered
console.log(this.user.refreshList$.getValue()); // try to get value of my Behavior
}
getUserList() {
this.user.getUsers().subscribe(
(users) => {
console.log(users);
this.users = users;
this.usersDataSource = new MatTableDataSource<IUsers>(copyOf(this.users));
this.usersDataSource.paginator = this.paginator;
},
(error) => {
console.log(error);
}
)
}
refreshTable(event: BehaviorSubject<boolean>){
console.log(event.getValue()); // get the new value of behaviorSubject after file upload successfully
event.subscribe(() => {
console.log("Get new value");
//this.getUserList();
});
}
}
ListUserComponent.html
<div >
<table mat-table [dataSource]="users">
<ng-container matColumnDef="username">
<th mat-header-cell *matHeaderCellDef> Username </th>
<td mat-cell *matCellDef="let element"> {{ element.username }} </td>
</ng-container>
<ng-container matColumnDef="lastName">
<th mat-header-cell *matHeaderCellDef> Last Name </th>
<td mat-cell *matCellDef="let element"> {{ element.LastName }} </td>
</ng-container>
<ng-container matColumnDef="firstName">
<th mat-header-cell *matHeaderCellDef> firstName </th>
<td mat-cell *matCellDef="let element"> {{element.firsName}} </td>
</ng-container>
</table>
<mat-paginator [pageSizeOptions]="[3, 5]" showFirstLastButtons> </mat-
paginator>
</div>
<app-FileUpload (emitUpload)="refreshTable($event)"></app-FileUpload>
CodePudding user response:
as of how Material Tables works, you need to inform the table that something has changed (for performance reasons)
this.table.renderRows();
see example: https://material.angular.io/components/table/examples#table-dynamic-array-data
CodePudding user response:
For those who got the same problem, i finally found a solution. Add a short timer before calling the list. Bellow the way it looks like :
- Add add a Subject and an Observable in your service to notify when there some change
UserService.ts
private _refresh$ = new Subject<any>();
get refresh$(){
return this._refresh$; // Will push value when any changes happend
}
listen(): Observable<any> {
return this._refresh$.asObservable(); // Will listen for the value that was pushed
}
- From method you need to perform , push a value using your Subject created in your Service
FileUpload.component.ts
upload(){
//process to upload file
this.etudiant.refresh$.next('uploaded'); // When the file is uploaded push a value by using your Subject created in your Service.
}
- From another method, listen the value that has been pushed by your subject and add a short timer before calling your refreshed list
ListUser.component.ts
constructor(private user: UserService) { }
ngOnInit() {
/* From your service, call your listen method created previously, responsible
to get the value pushed by the "_refresh$". Then add a timer (Ex: 500ms) before
calling your list */
this.user.listen().pipe(debounceTime(500)).subscribe(() => {
this.getUsers();
});
}
// When we finish with your Subject, will unsubscribe for performance reason (Release memory space)
ngOnDestroy() {
this.user.refresh$.unsubscribe();
}
Hopefully it will help. If someone got a better solution let me know, Thank's by advance.