0

I've created component which takes an @Input() value but I always get undefind. Here's my code:

parent.html

<added-item
      [minItemValueLength]="minItemValueLength"
      [maxItemValueLength]="maxItemValueLength"
      [listOfItems]="listOfItems"
  ></added-item>

children.ts

export class AddedItemComponent implements OnInit, OnChanges{

  @Input() minItemValueLength: number;
  @Input() maxItemValueLength: number;
  @Input() listOfItems: string[];

  ngOnInit() {
    console.log(this.minItemValueLength)      // return 3 
    console.log(this.listOfItems)             // return undefined
  }
}

parent.ts

export class LocationsTabComponent implements OnInit {
  listOfItems: string[];
  minItemValueLength = 3;
  maxItemValueLength = 15;

  public ngOnInit(): void {
    this.locationService.getLocations().subscribe((locations) => {
      this.getLocationsList();
      console.log(this.listOfItems)    // return Array(6)
    });
  }
  private getLocationsList() {
    this.listOfItems = this.locations.map((location: Location) => location.name);
    console.log(this.listOfItems)    // return Array(6)
  }
}

If I use ngOnChanges() in children than it at first output me:

data undefined and then:

data Array(6)

How can I get this value in onInit?

Would be really grateful for any help!

0

3 Answers 3

2

This is because you assign

listOfItems = ...

in an async callback method.

If you want to detect the changes, you should implement onChanges interface and implement the corresponding hook method.

export class AddedItemComponent implements OnInit, OnChanges{

    @Input() minItemValueLength: number;
    @Input() maxItemValueLength: number;
    @Input() listOfItems: string[];

    ngOnInit() {
        console.log(this.minItemValueLength)      // return 3 
        console.log(this.listOfItems)             // return undefined
    }
    
    ngOnChanges(changes: SimpleChanges): void {
        if (changes.listOfItems) {
            console.log(this.listOfItems)
        }
    }

}
Sign up to request clarification or add additional context in comments.

Comments

1

The value isn't always undefined only on the time the component is created, and this is because you passed as such.

Process:

  1. Parent is creating and ngOnInit is starting.
  2. ngOnInit has Observable\Promise\Async method, which means we're not waiting for the response, thus the value is still undefined.
  3. Child component is created and executing the ngOnInit. value still undefined.
  4. The Observable\Promise\Async method is now finally finished and custom callback you created now assigned the value, and the value is passed to the child component. So of course child ngOnInit will not accept it because the component was already created.

There are couple of solutions:

  1. Put *ngIf="listOfItems" on added-item.
  2. Decorate Parent as async ngOnInit, change: .subscribe to .toPromise e.g: await this.locationService.getLocations().toPromise..., now parent ngOnInit will wait for response.

1 Comment

Thanks a lot for explanation! That's really helped! Now I understand all this process.
1

Since your subscribing to the locations, you can use async to wait until the response is fully resolved or otherwise you have to implement OnChanges interface.

public async ngOnInit(): void {
await this.locationService.getLocations().toPromise().then((locations) => {
  this.getLocationsList();
  console.log(this.listOfItems)    // return Array(6)
});
}
private getLocationsList() {
  this.listOfItems = this.locations.map((location: Location) => location.name);
  console.log(this.listOfItems)    // return Array(6)
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.