angulartypescriptasynchronouslazy-loadingrerender

New components aren't Re-rendering when data has been fetched but they do re-render if it's an old component


I'm working on an already started project and when using the ngFor directive it's not re rendering once it gets the data, i tested this copying the exact same code on 2 components if it's an old component it works but not in the new ones, i have tested this in different new components and in none of them work, this is so oddly specific that i don't know if i can even replicate this.

(I have tried with trackBy, async, changeDetection, Observables, Promises adding the logic to the OnInit block)

both components are part of a module AdmisionesModule

@NgModule({
  declarations: [    
    newComponent,
    oldComponent,
    ...
  ],
  imports: [
    AdmisionesRoutingModule
    ...
  ],

this is AdmisionesRoutingModule

const routes: Routes = [
  { path: '', component: containBothComponent },
  { path: 'comprobantePago/:referencia', component: containBothComponent },
  { path: 'error/:codigo', component: containBothComponent },
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule],
})
export class AdmisionesRoutingModule {}

then AdmisionesModule is being called in my app-routing.module.ts

const routes: Routes = [
  { path: '', redirectTo: '/usuario/iniciar-sesion', pathMatch: 'full' },
  { path: 'usuario', loadChildren: () => import('@login/login.module').then(mod => mod.LoginModule) },
  { path: 'admisiones',canActivate: [SecurityGuard], loadChildren: () => import('@admisiones/admisiones.module').then(mod => mod.AdmisionesModule)},
];

the ngFor code is as simple as it gets

newComponent.ts/newComponent.ts

options: any[];

constructor(public myServices: MyService) {
this.myServices.askService().subscribe({
      next(values: any[]) {
        this.options = values;
      },
      error(err) {
        console.error(err);
      },
    });
}

newComponent.html/newComponent.html

<p *ngFor="let option of options">{{option.economic_sector_desc}}</p>

Project and environment info:
Angular CLI: 16.1.8
Node: 18.15.0
Package Manager: npm 9.7.2
Angular: 16.2.7
@angular-devkit/architect 0.1602.4
@angular-devkit/build-angular 16.2.4
@angular-devkit/core 16.2.4
@angular-devkit/schematics 16.1.8
@angular/cdk 16.2.6
@angular/cli 16.1.8
@angular/material 16.2.6
@schematics/angular 16.1.8
rxjs 7.8.1
typescript 5.1.6
zone.js 0.13.3

if there's anything i'm missing, please let me know.

(I have tried with trackBy, async, changeDetection, Observables, Promises adding the logic to the OnInit block)

Also testing the code on different components on the original ones that came with the project works correctly the one i added doesn't work.

I want the component to render by itself if the ngFor directive gets a new set of data and i want to know why isn't it working in order to avoid future problems.


Solution

  • Have you CommonModule in your imports - could be cased by this.

    find more info in [ngFor][1] documentation

    You can use asyncPipe for best practiced approach of rendering or data

    declare observable in your component

    public options$:Observable<any[]> = this.myServices.askService();
    

    modify your template as follow

    <ng-container *ngIf="option$ | async as optionsList">
      <div *ngFor="let option of optionsList">
        {{ option }}
      </div>
    </ng-container 
    

    Thanks! [1]: https://v16.angular.io/api/common/NgFor