Tengo un componente que recibe una serie de image
objetos como Input
datos.
export class ImageGalleryComponent {
@Input() images: Image[];
selectedImage: Image;
}
Me gustaría que cuando el componente cargue el selectedImage
valor se establezca en el primer objeto de la images
matriz. He intentado hacer esto en el OnInit
gancho del ciclo de vida de esta manera:
export class ImageGalleryComponent implements OnInit {
@Input() images: Image[];
selectedImage: Image;
ngOnInit() {
this.selectedImage = this.images[0];
}
}
esto me da un error Cannot read property '0' of undefined
que significa que el images
valor no está establecido en esta etapa. También probé el OnChanges
gancho, pero estoy atascado porque no puedo obtener información sobre cómo observar los cambios de una matriz. ¿Cómo puedo lograr el resultado esperado?
El componente principal se ve así:
@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
);
}
}
La plantilla del componente principal tiene esto
...
<image-gallery [images]="images"></image-gallery>
...
javascript
angular
typescript
Optimus Pette
fuente
fuente
images
rellenan los datos en el componente principal? Es decir, ¿es a través de una solicitud http? Si es así, es mejor que tenga el ImageGalleryComponent subscribe () al http observable.images
son solo una parte de los datos que utiliza el padre de esta manera, lo{profile: {firstName: "abc", lastName: "xyz", images: [ ... ]}}
que significa que si me suscribo al niño, aún tendré que suscribirme al padre y me gustaría evitar la repeticiónRespuestas:
Las propiedades de entrada se rellenan antes de que
ngOnInit()
se llame. Sin embargo, esto supone que la propiedad principal que alimenta la propiedad de entrada ya está poblada cuando se crea el componente secundario.En su escenario, este no es el caso: los datos de las imágenes se completan de forma asincrónica desde un servicio (de ahí una solicitud http). Por lo tanto, la propiedad de entrada no se completará cuando
ngOnInit()
se llame.Para resolver su problema, cuando los datos se devuelvan desde el servidor, asigne una nueva matriz a la propiedad principal. Implementar
ngOnChanges()
en el niño.ngOnChanges()
se llamará cuando la detección de cambio angular propague el nuevo valor de la matriz hasta el niño.fuente
ngOnchanges()
en el niño,Cannot read property '0' of undefined
aparece el error . Pero la aplicación puede continuar sin problemas. Este error se debe a que inicialmente no se ha completado la propiedad de entrada. Se completa con la segunda llamadangOnChanges()
cuando se reciben los datos de la llamada asíncrona. Para mi caso, además de esta solución, agregué la protección contra el operador nulo en el html. Claramente resolvió el error.También puede agregar un configurador para sus imágenes que se llamará cada vez que cambie el valor y puede establecer su imagen seleccionada por defecto en el propio configurador:
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; }
fuente