0

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 { }
orangeBall
  • 93
  • 1
  • 5
  • 2
    Instead of using this.employees.push(e); try to use this.employees = [...this.employees, e] – MikeOne Aug 24 '21 at 09:40
  • 1
    do what @MikeOne wrote . and change your pattern instead of subscribe in the component subscribe in the template – yehonatan yehezkel Aug 24 '21 at 09:44
  • @MikeOne thanks. I forgot to mention I already tried this solution, didn't change the behavior – orangeBall Aug 24 '21 at 09:47
  • @yehonatanyehezkel So I just tried subscribing in the template using an async pipe. As other approaches, it works as long as I don't use the router. Once I navigate, the pipe is broken too. – orangeBall Aug 24 '21 at 10:25
  • 1
    What is the route for the component? It might be related to routeReuse strategy. – Gergő Éles Aug 24 '21 at 17:53
  • @GergőÉles thanks. The behavior is the same with any route. For instance `'/employees' => '/employee/1'` produces the same bug as `'/employees' => '/contact'` or `'/employees' => ''` . I double checked to make sure. – orangeBall Aug 25 '21 at 07:12
  • @GergőÉles I edited my question with additional information regarding the routes. We might be onto something here. – orangeBall Aug 25 '21 at 07:43
  • @orangeBall This reminds me of an issue I had with the router trying to reuse the component resulting the not updated view. Could you try this little snippet below? If it does not could you could provide a stackblitz example I am more than happy to look into it. constructor( private router: Router ) { this.router.routeReuseStrategy.shouldReuseRoute = function(){ return false; } } – Gergő Éles Aug 29 '21 at 10:26

0 Answers0