I'm trying to figure out a weird behavior from Angular Router 12.2.0.
I'm using websockets to update a table in real time.
Everything works as expected as long as I don't use the router (either by clicking an achor tag with a [routerLink]
attribute or by calling router.navigate
method).
Steps to reproduce
- Navigate to the component hosting the table, say
/employees
- Confirm the table is updated in real time
- Navigate away
- Come back to
/employees
- The table is now frozen with the data received at page load
The issue doesn't come from the socket. The component keeps receiving data from the server and updates the model as expected. Only the GUI is out of sync with the model.
Oddly enough, the UI will reflect the changes if I trigger the exact same updates manually (i.e. by executing a function bound to a button).
The only way to restore the live updates is to manually reload the entire page using F5
.
Is this behavior related to the "angular zone"? Why does this behavior only happen when I navigate using angular router? What is going on?
Code example
The code is simple. I simply subscribe to a STOMP Broker location by providing an uri and a callback. I update the model in the callback. The model (a simple array) is rendered in the view using an *ngFor
directive.
// callback executed everytime a message from the server is received
const callback = (message: Message) => {
const e: Employee = JSON.parse(message.body);
// update the model
this.employees.push(e);
}
this.stompClient.subscribe(uri, callback, headers);
And in the template:
<td *ngFor="let e of employees">{{e.name}}</td>
What I tried
I of course tried the following approaches:
- ApplicationRef.tick()
- NgZone.run(callback)
- ChangeDetectorRef.detectChanges()
None of the solutions of these answers worked for me:
How to force a component's re-rendering in Angular 2?
Angular2 View Not Changing After Data Is Updated
Angular 6 View is not updated after changing a variable within subscribe
Angular component not updating when input changes value
ANGULAR 7 reload component view
Triggering change detection manually in Angular
The correct method of updating a MatTableDataSource in angular 2 version 6
Nothing solved my issue. The view stays frozen every time I use the router. It's getting to the point where I'm thinking about using window.location.reload()
if nothing else works.
Update
I tried both yehonatan yehezkel and MikeOne suggestions in the comments. They both work as long as I don't use the router. As soon as I start navigating, the view is not updated anymore. So this confirms the common denominator is the router here. What am I missing? Why does the router prevent the view from updating?
Update2
Addressing Gergő Éles comment:
Could the problem come from the way I declared the routes for my nested modules?
In app-routing.module
const routes: Routes = [
{
path: employees
canActivate: [CanActivateRoute],
loadChildren: () => import('./modules/employee/employee.module').then(mod => mod.EmployeeModule)
}
];
@NgModule({
imports: [
RouterModule.forRoot(routes),
...
],
exports: [RouterModule]
})
export class AppRoutingModule { }
And in employee.module
:
const routes: Routes = [
{
path: '',
children: [
{
path: '',
component: EmployeeListComponent
}
]
}
];
@NgModule({
imports: [
RouterModule.forChild(routes),
...
],
declarations: [
EmployeeListComponent,
...
]
})
export class EmployeeModule { }