角度4绑定图像无法读取未定义的属性

时间:2017-06-16 21:35:51

标签: angular binding angular-ui-router django-rest-framework

我有一个Angular 4.0组件,它有一个NgFor cicle的相对HTML,它为从我的api(用django rest框架开发)中检索的每个“book对象”创建一个card元素。

BROWSER.HTML

<div *ngFor="let book of books" class="col s12 m2">
      <div class="card">
        <div class="card-image">
          <img  src="{{book.img_url}}" >
        </div>
        <div class="card-content">
          <span class="card-title">{{book.book_title}}</span>
          <p>ISBN: {{book.isbn}}</p>
        </div>
        <div class="card-action">
          <a  [routerLink]="['/detail', book.isbn]">This is a link</a>
        </div>
      </div>
    </div>

我路由器的路线是

ROUTER.TS

const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'signup', component: SignupComponent },
  { path: 'home', component: HomeComponent },
  { path: 'books', component: BrowserComponent },
  { path: 'detail/:isbn', component: BookDetailComponent },
];

我想访问每个图书对象的详细信息页面。在我的详细信息组件中,我有:

BookDetailComponent.ts

export class BookDetailComponent implements OnInit {
  book: Book;
  constructor(
    private bookService: BookService,
    private route: ActivatedRoute,
    private location: Location
  ) { }

  ngOnInit(): void {
    this.route.params
      .switchMap((params: Params) => this.bookService.getBook(+params['isbn']))
      .subscribe(book => this.book = book);
    console.log(this.book);
  }

我的图书服务是:

BOOKSERVICE.TS

@Injectable()
export class BookService {

  private headers = new Headers({ 'Content-Type': 'application/json' });
  private booksUrl = 'http://localhost:8000/api/books/';

  getBook(isbn: number): Promise<Book> {
    const url = `${this.booksUrl}${isbn}/`;
    return this.http.get(url)
      .toPromise()
      .then(response => {
        console.log(response.json());
        return response.json() as Book;
      })
      .catch(this.handleError);
  }

当我在

中使用此html代码时

BookDetailComponent.html

<div class="container">
  <div class="row center"">
    <div class="card white col s8 offset-s2 text-cyan">
      <div class="row">
        <div class="col s3"><img src="{{book.img_url}}"></div>
        <div class="col s9"></div>
      </div>
    </div>
  </div>
</div>

我在Chrome控制台中:

ERROR TypeError: Cannot read property 'img_url' of undefined
    at Object.eval [as updateRenderer] (BookDetailComponent.html:7)
    at Object.debugUpdateRenderer [as updateRenderer] (core.es5.js:12822)
    at checkAndUpdateView (core.es5.js:12127)
    at callViewAction (core.es5.js:12485)
    at execComponentViewsAction (core.es5.js:12417)
    at checkAndUpdateView (core.es5.js:12128)
    at callViewAction (core.es5.js:12485)
    at execEmbeddedViewsAction (core.es5.js:12443)
    at checkAndUpdateView (core.es5.js:12123)
    at callViewAction (core.es5.js:12485)

ERROR CONTEXT DebugContext_ {view: Object, nodeIndex: 12, nodeDef: Object, elDef: Object, elView: Object}

和这个

Error: Uncaught (in promise): TypeError: Cannot read property 'img_url' of undefined
TypeError: Cannot read property 'img_url' of undefined
每次访问该页面时,

3-4次。总共有11个错误,有时候是19 ......

但是我的对象被正确接收了,我有

XHR finished loading: GET "http://localhost:8000/api/books/9788808122810/".

Object {isbn: "9788808122810", book_title: "My Title", pub_date: "2017-06-16T17:57:31Z", img_url: "https://img.ibs.it/images/someimage.png"}

并且我的页面中的图片实际上显示为。我只是想知道为什么所有这些错误......

我的书课,只是为了确保你有所有的信息

export class Book {
  isbn: number;
  book_title: string;
  pub_date: string;
  img_url: string;
}

2 个答案:

答案 0 :(得分:4)

问题在于,当您的组件( BookDetailComponent )呈现时, book 属性为null,因为订阅方法为“ route:ActivatedRoute “服务是异步的(了解rxjs的Observables )但却没有返回。如果 book 属性不为null,则需要使用 async pipe 或使用 * ngIf 运算符进行验证 BookDetailComponent.html

Angular异步管道参考:https://angular.io/api/common/AsyncPipe

可观察的参考:http://reactivex.io/documentation/observable.html

答案 1 :(得分:2)

只需添加一个“?”像下面的“书”之后。它使对象成为可选对象,如果在渲染时不可用,则不会给出错误。

<div *ngFor="let book of books" class="col s12 m2">
  <div class="card">
    <div class="card-image">
      <img  src="{{book?.img_url}}" >  <!--Check this line-->
    </div>
    <div class="card-content">
      <span class="card-title">{{book.book_title}}</span>
      <p>ISBN: {{book.isbn}}</p>
    </div>
    <div class="card-action">
      <a  [routerLink]="['/detail', book.isbn]">This is a link</a>
    </div>
  </div>
</div>