Home > Enterprise >  Angular - Error for Type not assignable in data bind
Angular - Error for Type not assignable in data bind

Time:08-25

I'm trying to bind some data from a parent component to its child component and I keep getting the same type error.

I have a table full of cells with movie info and I want to open a modal with further details of a movie when its cell is clicked. This involves some API data fetching.

As such, I have my app-movie-list template:

</table>
...
    <tbody>
        ...
        <tr *ngFor='let movie of movieList$ | async' (click)="selectMovie(movie.id)">
            <td >{{ movie.rank }}</td>
            <td >{{ movie.title }}</td>
            ...
        </tr>
    </tbody>
</table>

<app-movie-detail 
    [isDetailDisplayed]="isDetailDisplayed"
    [movie]="(selectedMovie$ | async)"
    ...
>
</app-movie-detail>

When a cell is clicked, an API request is made in the component:

selectedMovie$!: Observable<MovieDetails>;
...
...
selectMovie(id: string) {
    this.isDetailDisplayed = true;
    this.selectedMovie$ = this.apiManager.fetchMovieById(id);
}

The API request in question:

fetchMovieById(id: string): Observable<MovieDetails> {
    const endpoint = this.url   "/api/movies/"   id;
    return this.http.get<MovieDetails>(endpoint);
}

And finally, in my app-movie-detail I just have the input like so:

@Input() movie!: MovieDetails;

However, I keep getting the same compilation error:

enter image description here

Can anyone help me understand why I keep getting this type error? Thanks in advance.

CodePudding user response:

The fetchMovieById(id) probably returns MovieDetails | null. I assume it fetches the data from a database. So either you handle the case of null in the parent component or you change your @Input() movie!: MovieDetails; to @Input() movie!: MovieDetails | null;

CodePudding user response:

The observable selectedMovie$ will be suscribed to once the component is loaded due to the async pipe. Until the first request is actually performed you will get null.

You could add a filter to the request like

this.selectedMovie$ = this.apiManager.fetchMovieById(id).pipe(filter(value => !!value));

I think I'd not directly pass in the request-result into the databinding though. Instead I would use e.g. a BehaviorSubject/asObservable combination and next() the result of the fetch (still have the filter on that observable though or have a default/empty details value). That way you could use the info in different places as well if needed (a second async pipe would create another http request).

  • Related