【问题标题】:Angular Cannot read property 'subscribe' of undefinedAngular无法读取未定义的属性“订阅”
【发布时间】:2018-07-03 18:52:05
【问题描述】:

我正在尝试使用来自服务器的 json 响应创建一个动态菜单,但出现此错误:

MenuComponent.html:4 错误类型错误:无法读取未定义的属性“订阅” 在 MatMenuTrigger.push../node_modules/@angular/material/esm5/menu.es5.js.MatMenuTrigger.ngAfterContentInit

当我点击按钮时,它会说:

错误类型错误:无法读取未定义的属性“createEmbeddedView” 在 ViewContainerRef_.push../node_modules/@angular/core/fesm5/core.js.ViewContainerRef_.createEmbeddedView

我猜按钮无法创建,因为 json 响应尚未准备好,但我不知道如何修复它。

Component.ts

export class MenuComponent implements OnInit {
  branchList: Branches = new Branches(); //read somewhere that I need to initialize, not sure

  ngOnInit(): void {
    this.http.get('http://demo8635782.mockable.io/branches').subscribe((data: any) => {
      if (data === null) {
        console.log('api request returns empty!');
      }
      this.branchList = data;
    });
  }

  constructor(private breakpointObserver: BreakpointObserver, private http: HttpClient) {
  }
}

Template.html

<button mat-button [matMenuTriggerFor]="branchesMenu">Branches</button>
<mat-menu #branchesMenu="matMenu">
  <div *ngFor="let branch of branchList?.branches">
    <button mat-menu-item [matMenuTriggerFor]="branch?.name">{{branch.name}}</button>
  </div>
</mat-menu>

Stackblitz

【问题讨论】:

  • 您不确定的那一行.. 从branchList: Branches = new Branches(); 更改为branchList: Branches; 怎么样?它会改变错误吗? ...而且我从未见过为 ngOnInit 声明的类型 - 不需要
  • 不,它不会改变任何东西,我从这里看到了它:link
  • 请创建一个minimal reproducible example,我推荐stackblitz.com
  • @Igor 我添加了示例
  • 返回数据的接口不能和branchList的接口相似,否则会报错。

标签: angular


【解决方案1】:

我在这个stackblitz 中解决了它 我使用正确版本的材料和角度更新依赖项,使用模板中的 observable 将按钮包装在 ngIf 中,还删除了 mat-menu-item 的 matMenuTriggerFor 并在 app.module 中导入 BrowserAnimationsModule。

编辑添加子菜单,为此您必须在 ngFor 迭代中创建子菜单。

【讨论】:

  • 谢谢,但我需要 matMenuTriggerFor 因为我将只根据该 json 响应创建一个菜单。
  • 编辑响应添加子菜单
【解决方案2】:

你把它复杂化了。这只是 HttpClient.get 的返回类型的问题。显然它没有返回 Observable,您需要阅读该库的文档以了解原因。

您还可以大大简化代码:

export class AppComponent  {
  readonly branches = this.http
    .get('https://demo8635782.mockable.io/branches')
    .pipe(
    map((data) => data as Branches),
    map(({branches}) =>branches),
    shareReplay(),
  );    
  constructor(private http: HttpClient) {}
}


<button mat-button [matMenuTriggerFor]="branchesMenu">Branches</button>
<mat-menu #branchesMenu="matMenu">
 <button mat-menu-item *ngFor="let branch of (branches | async)">{{branch.name}}</button>
</mat-menu>

编辑:不,完全错误。正如 Daniel Caldera 在下面指出的那样,实际的问题是 mat-menu-item 的 matMenuTriggerFor。

其他问题:

  1. 您需要导入 BrowserAnimationsModule
  2. 您需要导入操作符(map、shareReplay)
  3. 您需要在 CSS 中包含主题
  4. 您不应该像我最初建议的那样取消对异步的引用

Here 是我的工作版本。

【讨论】:

  • 我试过你的代码,但它给了我关于地图的错误:缺少函数实现。即使我在 tsconfig 中添加了“target”:“es6”和“lib”:[“es6”、“es2017”、“es2015”、“dom”、“esnext”]。我是 ​​Typescript 和 Angular 的新手,所以我不知道怎么解决。
  • @Cagurtay -- 这是否意味着您解决了您的get() 问题?我在 pipe(现在已修复)这个词后面少了一个括号,也许就是这样。
  • 不,它会给地图和重播错误。 stackblitz
  • 更新了答案。
  • 谢谢,它正在工作,但现在我需要找到一种方法来解析 JSON 并从中创建嵌套菜单,这就是我使用 matMenuTriggerFor 的原因
【解决方案3】:

我有类似的问题。登录以刷新我的令牌。 后端需要令牌,因此必须使用有效令牌发出请求。

确保您的请求中有有效的令牌。

检查您的后端。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-13
    • 2019-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-23
    • 2019-09-14
    相关资源
    最近更新 更多