javascript - Angular: ใน hook ของ lifecycle ไหนที่ข้อมูล input สามารถเข้าถึงได้ใน Component
ฉันมีคอมโพเนนต์ที่รับอาร์เรย์ของวัตถุ image เป็นข้อมูล Input
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];
}
}
นี่ทำให้ฉันเกิดข้อผิดพลาด Cannot read property '0' of undefined ซึ่งหมายความว่าค่า images ยังไม่ได้ถูกตั้งค่าในขั้นตอนนี้ ฉันก็ได้ลองใช้ hook OnChanges แล้ว แต่ฉันติดขัดเพราะไม่สามารถหาข้อมูลเกี่ยวกับการสังเกตการเปลี่ยนแปลงของอาร์เรย์ได้ ฉันจะทำอย่างไรเพื่อให้ได้ผลลัพธ์ตามที่คาดหวัง?
คอมโพเนนต์หลักมีลักษณะดังนี้:
@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
);
}
}
แม่แบบของส่วนประกอบหลักมีสิ่งนี้
...
<image-gallery [images]="images"></image-gallery>
...
คำตอบ #1
คุณสมบัติของอินพุตจะถูกเติมก่อนที่ ngOnInit() จะถูกเรียก อย่างไรก็ตาม สิ่งนี้สมมติว่าคุณสมบัติของพ่อแม่ที่ป้อนให้คุณสมบัติอินพุตนั้นถูกเติมแล้วเมื่อคอมโพเนนต์ลูกถูกสร้างขึ้น
ในสถานการณ์ของคุณ ไม่เป็นเช่นนั้น - ข้อมูลภาพกำลังถูกเติมแบบอะซิงโครนัสจากบริการ (ดังนั้นจึงเป็นการร้องขอ http) ดังนั้น property ของ input จะยังไม่ถูกเติมเมื่อ ngOnInit() ถูกเรียก
ในการแก้ปัญหาของคุณ เมื่อข้อมูลถูกส่งกลับมาจากเซิร์ฟเวอร์ ให้กำหนดอาร์เรย์ใหม่ให้กับคุณสมบัติของพาเรนต์ นำ ngOnChanges() ไปใช้งานในชิลด์ ngOnChanges() จะถูกเรียกเมื่อการตรวจจับการเปลี่ยนแปลงของ Angular ส่งค่าของอาร์เรย์ใหม่ลงไปยังชิลด์
คำตอบ #2
คุณยังสามารถเพิ่มตัวตั้งค่าสำหรับรูปภาพของคุณซึ่งจะถูกเรียกทุกครั้งที่ค่ามีการเปลี่ยนแปลง และคุณสามารถตั้งค่ารูปภาพเริ่มต้นที่เลือกในตัวตั้งค่าเองได้:
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;
}
