Mam komponent, który otrzymuje tablicę image
obiektów jako Input
dane.
export class ImageGalleryComponent {
@Input() images: Image[];
selectedImage: Image;
}
Chciałbym, gdy składnik ładuje selectedImage
wartość ustawioną na pierwszy obiekt images
tablicy. Próbowałem to zrobić w OnInit
haku cyklu życia w następujący sposób:
export class ImageGalleryComponent implements OnInit {
@Input() images: Image[];
selectedImage: Image;
ngOnInit() {
this.selectedImage = this.images[0];
}
}
to daje mi błąd, Cannot read property '0' of undefined
co oznacza, że images
wartość nie jest ustawiona na tym etapie. Próbowałem też OnChanges
haka, ale utknąłem, ponieważ nie mogę uzyskać informacji o tym, jak obserwować zmiany w tablicy. Jak mogę osiągnąć oczekiwany efekt?
Komponent nadrzędny wygląda następująco:
@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
);
}
}
Szablon komponentu nadrzędnego ma to
...
<image-gallery [images]="images"></image-gallery>
...
javascript
angular
typescript
Optimus Pette
źródło
źródło
images
dane są wypełniane w komponencie nadrzędnym? To znaczy, czy odbywa się to za pośrednictwem żądań http? Jeśli tak, może lepiej byłoby, gdyby składnik ImageGalleryComponent subskrybował () obserwowalny http.images
to tylko część danych, które są używane przez rodzica w ten{profile: {firstName: "abc", lastName: "xyz", images: [ ... ]}}
sposób, co oznacza, że jeśli zapiszę się w dziecku, nadal będę musiał zapisać się dla rodzica i chciałbym uniknąć powtórzeniaOdpowiedzi:
Właściwości wejściowe są wypełniane przed
ngOnInit()
wywołaniem. Zakłada się jednak, że właściwość nadrzędna, która dostarcza właściwości wejściowe, jest już wypełniona podczas tworzenia komponentu podrzędnego.W Twoim scenariuszu tak nie jest - dane obrazów są wypełniane asynchronicznie z usługi (stąd żądanie http). W związku z tym właściwość input nie zostanie wypełniona po
ngOnInit()
wywołaniu.Aby rozwiązać problem, po zwróceniu danych z serwera przypisz nową tablicę do właściwości nadrzędnej. Zaimplementuj
ngOnChanges()
w dziecku.ngOnChanges()
zostanie wywołana, gdy wykrywanie zmian kątowych propaguje nową wartość tablicy do elementu podrzędnego.źródło
ngOnchanges()
w dziecku błądCannot read property '0' of undefined
pojawia się. Jednak aplikacja może działać bez problemu. Ten błąd występuje, ponieważ początkowo właściwość wejściowa nie została wypełniona. Jest zapełniany przy drugim wywołaniu wngOnChanges()
momencie odebrania danych z wywołania asynchronicznego. W moim przypadku dodatkowo do tego rozwiązania dodałem ochronę przed operatorem null w html. To wyraźnie rozwiązało błąd.Możesz także dodać metodę ustawiającą dla swoich obrazów, która będzie wywoływana za każdym razem, gdy zmieni się wartość, i możesz ustawić domyślny wybrany obraz w samym programie ustawiającym:
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; }
źródło
Możesz go rozwiązać, po prostu zmieniając kilka rzeczy.
export class ImageGalleryComponent implements OnInit { @Input() images: Image[]; selectedImage: Image; ngOnChanges() { if(this.images) { this.selectedImage = this.images[0]; } } }
źródło