Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular: In which lifecycle hook is input data available to the Component

I have a component which receives an array of image objects as Input data.

export class ImageGalleryComponent {   @Input() images: Image[];   selectedImage: Image; } 

I would like when the component loads the selectedImage value be set to the first object of the images array. I have tried to do this in the OnInit lifecycle hook like this:

export class ImageGalleryComponent implements OnInit {   @Input() images: Image[];   selectedImage: Image;   ngOnInit() {     this.selectedImage = this.images[0];   } } 

this gives me an error Cannot read property '0' of undefined which means the images value isn't set on this stage. I have also tried the OnChanges hook but I'm stuck because i can't get information on how to observe changes of an array. How can I achieve the expected result?

The parent component looks like this:

@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    );  } } 

The parent component's template has this

... <image-gallery [images]="images"></image-gallery> ... 
like image 706
Optimus Pette Avatar asked Jun 24 '16 19:06

Optimus Pette


People also ask

What is the correct order of lifecycle hooks in Angular?

Lifecycle sequenceInitialize the directive/component after Angular first displays the data-bound properties and sets the directive/component's input properties. Called once, after the first ngOnChanges() . Detect and act upon changes that Angular can't or won't detect on its own.

Are inputs available in ngOnInit?

Input properties are populated before ngOnInit() is called. However, this assumes the parent property that feeds the input property is already populated when the child component is created. In your scenario, this is not the case – the images data is being populated asynchronously from a service (hence an http request).

Which lifecycle hook is called when a component rendering is done?

Render JavaScript with Initial Render To do that, we can use a widely used lifecycle hook called componentDidMount . The componentDidMount() method will be triggered as soon as the component is mounted or inserted into the DOM.


2 Answers

Input properties are populated before ngOnInit() is called. However, this assumes the parent property that feeds the input property is already populated when the child component is created.

In your scenario, this is not the case – the images data is being populated asynchronously from a service (hence an http request). Therefore, the input property will not be populated when ngOnInit() is called.

To solve your problem, when the data is returned from the server, assign a new array to the parent property. Implement ngOnChanges() in the child. ngOnChanges() will be called when Angular change detection propagates the new array value down to the child.

like image 60
Mark Rajcok Avatar answered Oct 13 '22 03:10

Mark Rajcok


You can also add a setter for your images which will be called whenever the value changes and you can set your default selected image in the setter itself:

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; } 
like image 24
Sachin Parashar Avatar answered Oct 13 '22 04:10

Sachin Parashar