如何在服务数据更改时动态重新渲染 Angular 组件

问题描述 投票:0回答:1

我正在开发一个带有侧边栏组件的 Angular 应用程序,该组件根据用户的数据显示不同的菜单项。如果用户尚未创建任何公司,则菜单应仅显示“Empresas”选项。公司创建后,完整的菜单应该可见。此功能是通过组件用于通信的服务来控制的。尽管设置了我的组件和服务来通知更改并对更改做出反应,但在添加新公司后,侧边栏不会重新呈现以反映更新后的状态,而无需手动重新加载页面。

用户创建公司后,应显示完整的菜单。我在侧边栏的 HTML 中使用条件渲染来实现此目的,如下所示:

<!-- 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>

在我的侧边栏组件 TypeScript 文件中,我尝试根据公司列表更改时通知的服务重新渲染组件。这在新公司加入后尤其重要。这是我的侧边栏组件的简化版本:

// 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);
        }
  }
}

创建公司后,Empresa 组件会调用服务中的函数来通知更改:

// 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();
  }
}

最后,我的服务通知更改如下:

// Empresas.service.ts snippet
import { Subject } from 'rxjs';

export class EmpresasService {
  private reRender = new Subject<void>();
  reRender$ = this.reRender.asObservable();

  emitFunction() {
    this.reRender.next();
  }
}

尽管有这些实现,但在添加新公司后,侧边栏似乎并未按预期重新呈现。我正在寻找有关如何正确强制侧边栏组件更新并反映新状态而无需手动重新加载页面的指导。

任何关于我可能遗漏或做错的事情的建议或见解将不胜感激。

angular typescript angular2-changedetection
1个回答
0
投票

当 Angular 组件重新渲染时,不会再次调用

constructor
ngOnInit
。相反,您需要来自您的服务的
menuItems
(或任何动态数据)并直接在模板中显示该变量。

我会将您的

ngOnInit
代码移至服务中,并让您的组件显示该服务中的属性(变量)。每当属性更新时,Angular 都会自动渲染它。无需使用
ChangeDetectorRef
或调用
render()
方法。 Angular 会处理它。

如果您想了解有关 Angular 组件生命周期和服务的更多信息,这里有一些超短读物:

© www.soinside.com 2019 - 2024. All rights reserved.