I am currently working on an Angular application that features a sidebar component displaying different menu items based on the user's data. The sidebar should only display an option for "Empresas" if the user has not created any company yet. Once a company is created, the full menu should become visible. This dynamic behavior is managed through a service that facilitates communication between components. Despite setting up the components and service to handle notifications and reactions to changes, the sidebar fails to re-render automatically to reflect the updated state after adding a new company.
When a user creates a company, the entire menu should be shown. I have implemented conditional rendering in the HTML of the sidebar as shown below:
<!-- Sidebar HTML snippet -->
<li routerLinkActive="active" class="nav-item" *ngIf="empresas.length === 0 && !visible">
<a routerLink="/empresas" class="nav-link">
<i class="material-icons">dashboard</i>
<p>Empresas</p>
</a>
</li>
<!-- Rest of the menu items -->
<ng-container *ngIf="visible">
<li routerLinkActive="active" *ngFor="let menuitem of menuItems" class="nav-item">
<!--If it's a single link-->
<a [routerLink]="[menuitem.path]" *ngIf="menuitem.type === 'link'" class="nav-link">
<i class="material-icons">{{menuitem.icontype}}</i>
<p>{{menuitem.title}}</p>
</a>
</li>
</ng-container>
In my Sidebar component TypeScript file, I am trying to trigger a re-render of the component based on a service that notifies when the list of companies changes, especially after adding a new company. Below is a simplified version of my Sidebar component:
// Sidebar component TS snippet
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
/* Other imports */
export class SidebarComponent implements OnInit {
nombre: string = '';
nombre_empresa: string = '';
empresas: any[] = [];
public visible: boolean = true;
constructor(private _empresas_service: EmpresasService, /* All services */) {
this._empresas_service.reRender$.subscribe(() => {
this.rerender();
});
}
rerender() {
this._cambios_empresas.detectChanges();
this.visible = true;
}
async ngOnInit() {
this.nombre = environment.usuario.nombre;
this.empresas = environment.usuario.empresas;
this.nombre_empresa = this.empresas.find(e => e.id == environment.empresa_id).nombre;
if(this.empresas.length === 0) this.visible = false;
await this._empresas_service.indexPanelAdmin();
this.menuItems = ROUTES.filter(menuItem => menuItem);
if (window.matchMedia(`(min-width: 960px)`).matches && !this.isMac()) {
const elemSidebar = <HTMLElement>document.querySelector('.sidebar .sidebar-wrapper');
this.ps = new PerfectScrollbar(elemSidebar);
}
}
}
When a company is created, the Empresa component calls a function in the service to notify about the change:
// Empresa.component.ts snippet
private async _store() {
try {
await this._spinner.show();
const objeto = await this.empresas_service.store(this.form.value);
this._toastr_service.success('Company successfully added!');
this.empresas_service.emitFunction(); // Event to notify the change
this._form_directive.resetForm();
this._inicializaForm();
this.close();
await this._spinner.hide();
} catch (error: any) {
this._toastr_service.error(error.error);
await this._spinner.hide();
}
}
Finally, my service notifies the change as follows:
// Empresas.service.ts snippet
import { Subject } from 'rxjs';
export class EmpresasService {
private reRender = new Subject<void>();
reRender$ = this.reRender.asObservable();
emitFunction() {
this.reRender.next();
}
}
Despite the above implementations, the sidebar does not re-render as expected after adding a new company. I am seeking advice on how to effectively force the sidebar component to update and reflect the new state without requiring manual page reloads.
Any suggestions or insights regarding potential oversights or errors in my approach would be greatly welcomed.