Angular2: не удается прочитать свойство 'name' из неопределенного

Я начинаю изучать Angular2. Я следовал Учебному пособию для Героев, предоставленному angular.io. Все работало нормально до тех пор, пока, будучи раздраженным беспорядком HTML с использованием шаблона, я использовал URL-адрес шаблона вместо него и переместил HTML-файл в файл hero.html. Сгенерированная ошибка: "Не удается прочитать свойство" имя "из неопределенного". Странно, что переменная heroes, которая указывает на массив объектов, может быть доступна, так что 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>

Вот фото:

введите описание изображения здесь

5 ответов

Решение

Переменная selectedHero является нулевой в шаблоне, поэтому вы не можете связать selectedHero.name как есть. Вам нужно использовать оператор elvis для этого случая:

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

Разделение [(ngModel)] в [ngModel] и (ngModelChange) также необходимо, поскольку нельзя назначить выражение, использующее оператор elvis.

Я также думаю, что вы хотите использовать:

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

вместо:

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

Вам просто нужно прочитать немного дальше, и вы были бы ознакомлены со структурной директивой *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 до тех пор, пока он не будет выбран, и, следовательно, становится правдивым.

Этот документ помог мне понять структурные директивы.

Во избежание этого вы также можете инициализировать элемент selectedHero вашего компонента пустым объектом (вместо того, чтобы оставить его неопределенным).

В вашем примере кода это даст что-то вроде этого:

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

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

Вы получили эту ошибку, потому что следовали плохо написанным указаниям в руководстве по Героям. Я столкнулся с тем же.

В частности, под заголовком " Отображать имена героев в шаблоне" указывается:

Чтобы отобразить имена героев в неупорядоченном списке, вставьте следующий фрагмент 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>

Обратите внимание на отсутствие элементов детализации из предыдущих работ.

Подобная ошибка автора может привести к довольно дикой погоне. Надеюсь, этот пост поможет другим избежать этого.

Эта линия

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

снаружи *ngFor и нет hero следовательно hero.name выходит из строя.

Это сработало для меня:

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

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

и убедитесь, что вы инициализировали, а также выбранный герой

selectedHero: Hero = new Hero();

В Angular есть оператор поддержки elvis для защиты от сбоя визуализации представления. Они называют это оператором безопасной навигации. Возьмите пример ниже

Текущее имя человека: {{nullObject?.Name}}

Поскольку он пытается получить доступ к свойству name с нулевым значением, все представление исчезает, и вы можете увидеть ошибку внутри консоли браузера. Он отлично работает с длинными путями свойств, такими как?.B?.C?.D. Поэтому я рекомендую вам использовать его каждый раз, когда вам нужно получить доступ к свойству внутри шаблона.

https://trungk18.com/experience/uncaught-type-error/

Другие вопросы по тегам