Mambo
Mambo

Reputation: 197

Input not initialized in ngOnInit

I'm building a little website in Angular and i'm facing a wall.

I got the following,

<app-details *ngIf="(selected | async)" [selected]="selected | async"></app-details>

In the parent, selected is an observable.

  public selected: Observable<any>;
  constructor(private store: Store<State>) { }

  ngOnInit() {;
    this.selected = this.store.pipe(select(selectSelectedChamp));
  }

In my child, I want to do some work on selected :

  @Input() selected: any;
  public data: Array<{
    preview: string,
    thumbnail: string,
    alt: string,
  }>
  constructor() { }

  ngOnInit(): void {
    this.data= this.selected.map(skin => {
      return {
        preview: ... ,
        thumbnail: ...,
        alt: ...
      }
    })
  }

Problem is, selected doesn't seems to be initalized, if I log it, it's empty, and I got an error on the map... Cannot read property 'map' of undefined Maybe adding the visual effect will help understanding. I want to be able to visualize image, skins and infos on different League Of legends characters on click.

On the first click, my variable is not initialized, ie. image is not displaying, On the second click tho', image is displaying, but one click late ? enter image description here enter image description here

Upvotes: 1

Views: 3885

Answers (3)

bryan60
bryan60

Reputation: 29325

you probably was to declare the async result as a template variable like so:

<app-details *ngIf="selected | async as selection" [selected]="selection"></app-details>

this way you're not subscribing multiple times, the initial value from the async pipe will always be undefined, you work around tht this way. next, you probably want to use a setter input:

  private _selected;
  @Input() 
  set selected(value: any) {
    this._selected = value;
    this.data = value.map(skin => {
      return {
        preview: ... ,
        thumbnail: ...,
        alt: ...
      }
    })
  }
  get selected() {
    return this._selected
  }

this way, that map routine will run everytime the input value changes.

Upvotes: 0

ng-hobby
ng-hobby

Reputation: 2199

Try this:

<app-details *ngIf="(selected | async) as selection" [selection]="selection"></app-details>
  @Input() selection: any;
  public data: Array<{
    preview: string,
    thumbnail: string,
    alt: string,
  }>
  constructor() { }

  ngOnInit(): void {
   this.selection.pipe(take(1)).subacribe(res => {
       // Your code here...
      }
    })
  }

Upvotes: 0

Pawel Kiszka
Pawel Kiszka

Reputation: 850

Change this part:

[champDetails]="selected | async"

to this:

[selected]="selected | async"

Explanation: The childs component @Input name is selected, so in parent you must use [selected]=.... Otherwise selected is undefined, hence the error Cannot read property map of undefined.

Upvotes: 3

Related Questions