Javascript 角度:其中生命周期挂钩是组件可用的输入数据

Javascript 角度:其中生命周期挂钩是组件可用的输入数据,javascript,angular,typescript,Javascript,Angular,Typescript,我有一个组件,它接收一组图像对象作为输入数据 export class ImageGalleryComponent { @Input() images: Image[]; selectedImage: Image; } 我希望在组件加载selectedImage值时将其设置为images数组的第一个对象。我曾尝试在OnInit生命周期挂钩中这样做: export class ImageGalleryComponent implements OnInit { @Input() ima

我有一个组件,它接收一组
图像
对象作为
输入
数据

export class ImageGalleryComponent {
  @Input() images: Image[];
  selectedImage: Image;
}
我希望在组件加载
selectedImage
值时将其设置为
images
数组的第一个对象。我曾尝试在
OnInit
生命周期挂钩中这样做:

export class ImageGalleryComponent implements OnInit {
  @Input() images: Image[];
  selectedImage: Image;
  ngOnInit() {
    this.selectedImage = this.images[0];
  }
}
@Component({
  selector: 'profile-detail',
  templateUrl: '...',
  styleUrls: [...],
  directives: [ImageGalleryComponent]
})

export class ProfileDetailComponent implements OnInit {
  profile: Profile;
  errorMessage: string;
  images: Image[];
  constructor(private profileService: ProfileService, private   routeParams: RouteParams){}

  ngOnInit() {
    this.getProfile();
  }

  getProfile() {
    let profileId = this.routeParams.get('id');
    this.profileService.getProfile(profileId).subscribe(
    profile => {
     this.profile = profile;
     this.images = profile.images;
     for (var album of profile.albums) {
       this.images = this.images.concat(album.images);
     }
    }, error => this.errorMessage = <any>error
   );
 }
}
这给了我一个错误
无法读取未定义的
的属性“0”,这意味着未在此阶段设置
图像
值。我也尝试了
OnChanges
hook,但我被卡住了,因为我无法获得有关如何观察数组变化的信息。我怎样才能达到预期的结果

父组件如下所示:

export class ImageGalleryComponent implements OnInit {
  @Input() images: Image[];
  selectedImage: Image;
  ngOnInit() {
    this.selectedImage = this.images[0];
  }
}
@Component({
  selector: 'profile-detail',
  templateUrl: '...',
  styleUrls: [...],
  directives: [ImageGalleryComponent]
})

export class ProfileDetailComponent implements OnInit {
  profile: Profile;
  errorMessage: string;
  images: Image[];
  constructor(private profileService: ProfileService, private   routeParams: RouteParams){}

  ngOnInit() {
    this.getProfile();
  }

  getProfile() {
    let profileId = this.routeParams.get('id');
    this.profileService.getProfile(profileId).subscribe(
    profile => {
     this.profile = profile;
     this.images = profile.images;
     for (var album of profile.albums) {
       this.images = this.images.concat(album.images);
     }
    }, error => this.errorMessage = <any>error
   );
 }
}
@组件({
选择器:“配置文件详细信息”,
templateUrl:“…”,
样式URL:[…],
指令:[ImageGalleryComponent]
})
导出类ProfileDetailComponent实现OnInit{
简介:简介;
错误消息:字符串;
图像:图像[];
构造函数(私有profileService:profileService,私有routeParams:routeParams){}
恩戈尼尼特(){
这是一个.getProfile();
}
getProfile(){
让profileId=this.routeParams.get('id');
this.profileService.getProfile(profileId).subscribe(
个人资料=>{
this.profile=profile;
this.images=profile.images;
for(配置文件的var相册。相册){
this.images=this.images.concat(album.images);
}
},error=>this.errorMessage=error
);
}
}
父组件的模板具有以下特性:

...
<image-gallery [images]="images"></image-gallery>
...
。。。
...

在调用
ngOnInit()
之前填充输入属性。但是,这假定在创建子组件时已填充为输入属性提供信息的父属性

在您的场景中,情况并非如此–图像数据是从服务异步填充的(因此是http请求)。因此,在调用
ngOnInit()
时,不会填充输入属性


要解决此问题,从服务器返回数据时,请为父属性指定一个新数组。在子对象中实现
ngOnChanges()
<当角度变化检测将新的数组值向下传播到子级时,将调用code>ngOnChanges()。

您还可以为图像添加一个setter,该setter将在值变化时调用,您可以在setter中设置默认的选定图像:

export class ImageGalleryComponent {
  private _images: Image[];

  @Input()
  set images(value: Image[]) {
      if (value) { //null check
          this._images = value;
          this.selectedImage = value[0]; //setting default selected image
      }
  }
  get images(): Image[] {
      return this._images;
  }

  selectedImage: Image;
}

你可以通过简单地改变一些事情来解决它

  export class ImageGalleryComponent implements OnInit {

  @Input() images: Image[];
  selectedImage: Image;

  ngOnChanges() {
      if(this.images) {
        this.selectedImage = this.images[0];
      }
  }

 }

如何在父组件中填充
图像
数据?即,是否通过http请求?如果是这样,您最好让ImageGalleryComponent subscribe()订阅http observable。@MarkRajcok
images
只是这样的父级使用的数据的一部分
{profile:{firstName:“abc”,lastName:“xyz”,images:[…]}
,这意味着如果我订阅子级,我仍然需要订阅父组件,并且我希望避免重复。如果在创建子组件时填充父组件中的图像数组,则应在调用ngOnInit()之前填充图像输入属性。您需要提供有关如何在父组件中填充映像数组的更多信息,以便任何人进一步帮助您(或创建显示问题的最小插入器)。@MarkRajcok我已添加父组件以及如何在其中填充映像。因此,是的,您的父组件似乎正在使用http(因为它正在使用服务)来填充其images属性。因为这是一个异步操作,子组件的输入属性不会在调用其ngOnInit()方法时填充。请将代码从ngOnInit()移动到ngOnChanges()我同意你的观点,因为我自己也面临着同样的问题。即使在我实现了
ngOnchanges()之后
在子级中,出现了错误
无法读取未定义的属性“0”。但是,应用程序可以毫无问题地继续。此错误是因为最初输入属性尚未填充。它是由第二次调用
ngochanges()填充的
当接收到来自异步调用的数据时。对于我的情况,除了此解决方案之外,我还在html中添加了防范null运算符。它清楚地解决了错误。@Mark..很好地解释并解决了我的问题。