我目前正在开展一个展示电影信息的项目。使用@Input(),我将电影细节从父组件(电影)绑定到子组件(电影细节)。
父组件(电影)
import { Component, OnInit } from '@angular/core';
import { IMovie } from './movie';
import { MoviesService } from './movies.service';
import { IPopular } from './popular';
import { HttpClient } from '@angular/common/http';
import { MovieDetailComponent } from '../movie-detail/movie-detail.component';
@Component({
selector: 'app-movies',
templateUrl: './movies.component.html',
styleUrls: ['./movies.component.css']
})
export class MoviesComponent implements OnInit {
moviesList: IPopular[] = [];
movie: IMovie;
selectedMovie: IMovie;
constructor(private _moviesService: MoviesService) { }
ngOnInit() {
this._moviesService.getPopularMovies()
.subscribe(moviesList => {
this.moviesList = moviesList;
},
error => console.log(error)
);
}
onSelect(movie: IMovie): void {
this.selectedMovie = movie;
window.setTimeout(function() {window.scrollTo(0, 5000); }, 300);
}
}
父HTML
<div>
<ul class="movies" *ngFor="let movie of moviesList.results">
<li [class.selected]="movie === selectedMovie" (click)="onSelect(movie)">
<img class="poster" [src]="'https://image.tmdb.org/t/p/w200/'+ movie.poster_path">
<br> {{movie.title}}
</li>
</ul>
</div>
<app-movie-detail [movie]='selectedMovie'></app-movie-detail>
iMovie中
export interface IMovie {
vote_count: number;
id: number;
video: boolean;
vote_average: number;
title: string;
popularity: number;
poster_path: string;
original_language: string;
original_title: string;
genre_ids: number[];
backdrop_path: string;
adult: boolean;
overview: string;
release_date: string;
}
IPopular
import { IMovie } from './movie';
export interface IPopular {
results: Array<IMovie>;
page: number;
total_results: number;
dates: DateTimeFormat;
total_pages: number;
}
子组件
import { Component, OnInit, Input, OnChanges } from '@angular/core';
import { IResult } from './result';
import { IVideo } from './video';
import { IMovie } from '../movies/movie';
import { MovieDetailService } from './movie-detail.service';
@Component({
selector: 'app-movie-detail',
templateUrl: './movie-detail.component.html',
styleUrls: ['./movie-detail.component.css']
})
export class MovieDetailComponent implements OnChanges {
@Input() movie: IMovie;
videoList: IVideo[] = [];
video: IResult;
constructor(private _moviedetailService: MovieDetailService) { }
ngOnChanges() {
this._moviedetailService.getTrailer(this.movie.id)
.subscribe(videoList => {
this.videoList = videoList;
},
error => console.log(error)
);
}
ScrollToTop(): void {
window.setTimeout(function() {window.scrollTo(5000, 0); }, 300);
}
}
儿童HTML
<body class="background" [background]="'https://image.tmdb.org/t/p/original'+ movie.backdrop_path" *ngIf="movie">
<div class="detailpage">
<h1>{{ movie.title }}</h1>
<div>
<img class="poster" [src]="'https://image.tmdb.org/t/p/w300/'+ movie.poster_path">
<div class="movieinfo">
<h2>Overview:</h2>
<p>{{ movie.overview }}</p>
<h3>Rating:</h3>
<p>{{ movie.vote_average}} / 10</p>
<h3>Release Date:</h3>
<p>{{movie.release_date}}</p>
</div>
<div class="trailer" *ngFor="let videos of videoList.video">
<iframe [src]="'https://www.youtube.com/watch?v=' + videos.key"></iframe>
</div>
</div>
<span class="top" (click)="ScrollToTop()">Back to top</span>
</div>
</body>
IVideo
import { IResult } from './result';
export interface IVideo {
id: number;
results: Array<IResult>;
}
IResult
export interface IResult {
id: string;
iso_639_1: string;
iso_3166_1: string;
key: string;
name: string;
site: string;
size: number;
type: string;
}
使用此代码,我收到ERROR TypeError:无法读取未定义的属性'id'
ERROR TypeError: Cannot read property 'id' of undefined
at MovieDetailComponent.ngOnChanges (movie-detail.component.ts:22)
at checkAndUpdateDirectiveInline (core.js:12365)
at checkAndUpdateNodeInline (core.js:13893)
at checkAndUpdateNode (core.js:13836)
at debugCheckAndUpdateNode (core.js:14729)
at debugCheckDirectivesFn (core.js:14670)
at Object.eval [as updateDirectives] (SearchresultComponent.html:10)
at Object.debugUpdateDirectives [as updateDirectives] (core.js:14655)
at checkAndUpdateView (core.js:13802)
at callViewAction (core.js:14153)
你们有什么建议来解决这个问题?
答案 0 :(得分:0)
很可能是因为您的selectedMovie
为undefined
,直到您点击其中一个。你可以解决它隐藏你的电影细节组件,如果没有选择一个:
<app-movie-detail *ngIf="selectedMovie" [movie]="selectedMovie"></app-movie-detail>
答案 1 :(得分:0)
Angular(重新)设置数据绑定输入属性时的响应。该方法接收当前和先前属性值的SimpleChanges对象。 在ngOnInit()之前以及每当一个或多个数据绑定输入属性发生更改时调用。
将您的代码包装到条件检查中:crawl = crawl->getNode(key[i]);
if(this.movie) {...}
当输入属性发生变化时,将再次调用 ngOnChanges() {
if(this.movie) {
console.log(this.movie.id)
}
}
。
答案 2 :(得分:0)
启动子组件时this.movie
信息不可用。根据您的逻辑电影,仅在父组件中选择电影时才能使用详细信息。因此未定义的错误。
只有在电影详细信息可用时才应在ngOnChanges
中进行服务呼叫。尝试从子组件中更新ngOnChanges
,如下所示
ngOnChanges() {
if (this.movie) {
this._moviedetailService.getTrailer(this.movie.id)
.subscribe(videoList => {
this.videoList = videoList;
},
error => console.log(error)
);
}
}