首页 > 解决方案 > 从模板中的 *ngFor 调用时,Angular 10 服务未定义

问题描述

SessionService.component.ts我有以下logout()方法:

@Injectable({ providedIn: 'root' })
export class SessionService {
    constructor() {}

    // other session service stuff

    logout() {
        console.log('SessionService.logout');
        // do logout stuff
    }
}

以下MenuComponent.component.ts创建应用程序的菜单内容

import { SessionService } from '../session/session.service';

@Component({
  selector: 'app-menu',
  templateUrl: './menu.component.html',
  styleUrls: ['./menu.component.css']
})
export class MenuComponent implements OnInit {
    menuItems: Array<any>;

    constructor(private sessionService: SessionService) {}

    ngOnInit() {
        menuItems = [
            // logout menu item
            {
                name: 'Logout',
                action: this.signout
            }
        ];
    }

    // method called 'signout' to make it clear what method is called when
    signout() {
        console.log('MenuComponent.signout');
        this.sessionService.logout();
    }
}

最后,HTML 模板MenuComponent.component.html如下所示:

<mat-accordion class="example-headers-align" multi hideToggle displayMode="flat">
        <!-- App Signout -->
        <!-- THIS WORKS when (click)="signout()" is called -->
        <mat-expansion-panel class="menu-section mat-elevation-z0">
            <mat-expansion-panel-header (click)="signout()">
                <mat-panel-title fxLayout="row" fxLayoutAlign="start center">
                    <mat-icon class="menu-section-icon" svgIcon="logout"></mat-icon>
                    <span class="menu-section-title" tts="Logout"></span>
                </mat-panel-title>
            </mat-expansion-panel-header>
        </mat-expansion-panel>

        <!-- Menu Items inside ngFor loop -->
<!-- (click)="menuItem.action()" fails with the error described below, after this code block -->
        <mat-expansion-panel class="menu-section mat-elevation-z0" *ngFor="let menuItem of menuItems">
            <mat-expansion-panel-header (click)="menuItem.action()">
                <mat-panel-title fxLayout="row" fxLayoutAlign="start center">
                    <span class="menu-section-title">{{ menuItem.name }}</span>
                </mat-panel-title>
            </mat-expansion-panel-header>
</mat-accordion>

当我从模板中显式调用函数signout()时,我得到了预期的控制台输出,即

console.log('MenuComponent.signout');
console.log('SessionService.logout');

但是,当从数组中选择菜单项时,会话服务是未定义的,并且该SessionService.logout()函数永远不会执行。我得到错误

core.js:4442 错误类型错误:无法在执行ListenerWithErrorHandling(core.js :15225) 在 HTMLElement 的 wrapListenerIn_markDirtyAndPreventDefault (core.js:15266)。(platform-b​​rowser.js:582) 在 ZoneDelegate.invokeTask (zone-evergreen.js:402) 在 Object.onInvokeTask (core.js:27492) 在 ZoneDelegate.invokeTask (zone-evergreen.js:401) 在 Zone.runTask (zone-evergreen.js:174) 在 ZoneTask.invokeTask [作为调用] (zone-evergreen.js:483)

我认为它与所有组件的范围或初始化顺序有关,但对于我的一生,我无法弄清楚我需要改变什么......

先感谢您 :-)

标签: angularangular-services

解决方案


由于您在 menuitems 上调用方法,它指向 menuItems 对象,使用apply来指向当前类实例。

    <mat-expansion-panel class="menu-section mat-elevation-z0" *ngFor="let menuItem of menuItems">
        <mat-expansion-panel-header (click)="menuItem.action.apply(this)">
            <mat-panel-title fxLayout="row" fxLayoutAlign="start center">
                <span class="menu-section-title">{{ menuItem.name }}</span>
            </mat-panel-title>
        </mat-expansion-panel-header>

推荐阅读