【问题标题】:Angular2: Cannot read property 'name' of undefinedAngular2:无法读取未定义的属性“名称”
【发布时间】:2017-02-06 21:30:21
【问题描述】:

我开始学习 Angular2。我一直在关注 angular.io 提供的英雄教程。 一切正常,直到我对使用模板的 HTML 的混乱感到恼火,我使用模板 URL 代替它,并将 HTML 移动到名为 hero.html 的文件中。 生成的错误是“无法读取未定义的属性‘名称’”。 奇怪的是,可以访问指向对象数组的 heros 变量,这样 ngFor 就会根据数组中对象的数量生成正确数量的“li”标签。但是,无法访问数组对象的数据。 此外,即使是包含一些文本的简单变量,也不会在 HTML 中使用 {{}} 括号显示(请参阅提供的代码)。

app.component.ts

import { Component } from '@angular/core';
@Component({
  selector: 'my-app',
  templateUrl: './hero.html',
  styleUrls:['./styles.css']
})

export class AppComponent {
  title = 'Tour of Heroes';
  heroes = HEROES;
  selectedHero:Hero;

  onSelect(hero: Hero):void{
      this.selectedHero = hero;
  }
}

export class Hero{
   id: number;
   name: string;
}

const HEROES: Hero[] = [
   { id: 1, name: 'Mr. Nice' },
   { id: 2, name: 'Narco' },
   { id: 3, name: 'Bombasto' },
   { id: 4, name: 'Celeritas' },
   { id: 5, name: 'Magneta' },
   { id: 6, name: 'RubberMan' },
   { id: 7, name: 'Dynama' },
   { id: 8, name: 'Dr IQ' },
   { id: 9, name: 'Magma' },
   { id: 10, name: 'Tornado' }
];

hero.html

<h1>{{title}}</h1>
<h2>My Heroes</h2>
<ul class="heroes">
  <li *ngFor="let hero of heroes">
    <span class="badge">{{hero.id}}</span> {{hero.name}}
  </li>
</ul>
<h2>{{hero.name}} details!</h2>
<div>
    <label>id: </label>{{hero.id}}
</div>
<div>
    <label>name: </label>
    <input [(ngModel)]="selectedHero.name" placeholder="name">
<div>

这是一张照片:

【问题讨论】:

    标签: angular angular2-template


    【解决方案1】:

    在 Angular 中,有支持 elvis 运算符 ?. 来防止视图渲染失败。他们称其为安全导航运算符。举个例子:

    The current person name is {{nullObject?.name}}
    

    由于它试图访问 null 值的 name 属性,整个视图消失了,您可以在浏览器控制台中看到错误。它适用于长属性路径,例如a?.b?.c?.d。因此,我建议您每次需要访问模板中的属性时都使用它。

    【讨论】:

      【解决方案2】:

      变量selectedHero 在模板中是null,因此您不能按原样绑定selectedHero.name。对于这种情况,您需要使用elvis operator ?.

      <input [ngModel]="selectedHero?.name" (ngModelChange)="selectedHero.name = $event" />
      

      还需要将[(ngModel)] 分为[ngModel](ngModelChange),因为您不能分配给使用elvis 运算符的表达式。

      我也认为你的意思是使用:

      <h2>{{selectedHero?.name}} details!</h2>
      

      代替:

      <h2>{{hero.name}} details!</h2>
      

      【讨论】:

      • 谢谢。您已经大致确定了问题所在。但是,我仍然遇到问题。我将 {{hero.name}} 更改为 {{selectedHero.name}} 但仍然遇到相同的错误。我还按照您的指示更新了输入,但错误仍然存​​在。当 标记行被注释掉除了

        {{selectedHero.name}} 详细信息之外的所有内容!

        工作正常。因此我知道 selectedHero 对象的使用不正确。
      • 抱歉,我忘记了代码中的 elvis 运算符。我编辑了答案。应该是:{{selectedHero?.name}}
      • 太棒了!我刚刚添加了?,我的代码运行良好。
      • 谢谢,在我的属性修复我的条件数据绑定问题后添加?(如果属性存在)。您能否详细说明because you can't assign to an expression that uses the elvis operator. 的意思?
      • @TetraDev 您的示例之所以有效,是因为它只是一个数据绑定 [] 指令,而不是事件绑定 ()。如果 angular 能够解析语句并识别这些情况,那就太好了,但目前还没有。见github.com/angular/angular/issues/7697
      【解决方案3】:

      为了避免这种情况,您也可以将组件的 selectedHero 成员初始化为一个空对象(而不是让它未定义)。

      在您的示例代码中,这将给出如下内容:

      export class AppComponent {
        title = 'Tour of Heroes';
        heroes = HEROES;
        selectedHero:Hero = new Hero();
      
        onSelect(hero: Hero):void{
            this.selectedHero = hero;
        }
      }
      

      【讨论】:

        【解决方案4】:

        这对我有用:

        export class Hero{
           id: number;
           name: string;
        
           public Hero(i: number, n: string){
             this.id = 0;
             this.name = '';
           }
         }
        

        并确保你初始化以及 selectedHero

        selectedHero: Hero = new Hero();
        

        【讨论】:

          【解决方案5】:

          您收到此错误是因为您按照英雄教程中写得不好的说明进行操作。我遇到了同样的事情。

          具体来说,在标题在模板中显示英雄名称下,它声明:

          要在无序列表中显示英雄名称,请插入以下内容 标题下方和英雄详细信息上方的 HTML 块。

          后跟此代码块:

          <h2>My Heroes</h2>
          <ul class="heroes">
            <li>
              <!-- each hero goes here -->
            </li>
          </ul>
          

          它不会指示您替换以前的详细代码,它应该。这就是我们剩下的原因:

          <h2>{{hero.name}} details!</h2>
          

          在我们的*ngFor 之外。

          但是,如果您进一步向下滚动页面,您会遇到以下情况:

          显示英雄的模板应该是这样的:

          <h2>My Heroes</h2>
          <ul class="heroes">
            <li *ngFor="let hero of heroes">
              <span class="badge">{{hero.id}}</span> {{hero.name}}
            </li>
          </ul>
          

          请注意以前的工作中缺少细节元素。

          作者这样的错误可能会导致相当疯狂的追逐。希望这篇文章能帮助其他人避免这种情况。

          【讨论】:

            【解决方案6】:

            您只需要进一步阅读,您就会被介绍到 *ngIf 结构指令。

            selectedHero.name 还不存在,因为用户还没有选择英雄,所以它返回 undefined。

            <div *ngIf="selectedHero">
              <h2>{{selectedHero.name}} details!</h2>
              <div><label>id: </label>{{selectedHero.id}}</div>
              <div>
                <label>name: </label>
                <input [(ngModel)]="selectedHero.name" placeholder="name"/>
              </div>
            </div>
            

            *ngIf 指令将 selectedHero 保持在 DOM 之外,直到它被选中并因此变为真值。

            This document 帮助我理解了结构指令。

            【讨论】:

            • 这帮助我得到了我想要的东西,谢谢+1
            • 这对我也有帮助。事后这是有道理的,因为我的组件正在尝试渲染一个在异步操作完成时填充的对象。谢谢!
            【解决方案7】:

            这一行

            <h2>{{hero.name}} details!</h2>
            

            *ngFor 之外并且没有hero 因此hero.name 失败。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-12-06
              • 2022-01-22
              相关资源
              最近更新 更多