javascript - Angular: באיזה Hook של מחזור החיים הנתונים הנכנסים זמינים לרכיב
יש לי רכיב שמקבל מערך של אובייקטים מסוג image כנתוני Input.
export class ImageGalleryComponent {
@Input() images: Image[];
selectedImage: Image;
}
אני רוצה שכאשר הקומפוננטה נטענת, הערך של selectedImage יוגדר לאובייקט הראשון במערך images. ניסיתי לעשות זאת ב-hook של מחזור החיים OnInit כך:
export class ImageGalleryComponent implements OnInit {
@Input() images: Image[];
selectedImage: Image;
ngOnInit() {
this.selectedImage = this.images[0];
}
}
זה נותן לי שגיאה Cannot read property '0' of undefined שפירושה שהערך images לא מוגדר בשלב הזה. ניסיתי גם את הפונקציה 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). לכן, מאפיין הקלט לא יתמלא כאשר ngOnInit() נקרא.
כדי לפתור את הבעיה שלך, כאשר הנתונים מוחזרים מהשרת, הקצה מערך חדש לתכונת האב. יישם את ngOnChanges() בילד. ngOnChanges() ייקרא כאשר מנגנון גילוי השינויים של Angular מפיץ את הערך החדש של המערך לילד.
תשובה #2
אתה גם יכול להוסיף 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;
}
