Despite its presence, @Input() remains undefined

Currently, I am engrossed in a project that aims to display information about movies. By utilizing @Input(), I am establishing a connection between the movie details from the parent component (movies) and the child component (movie-detail).

Movies Parent Component

import { Component, OnInit } from '@angular/core';
import { IMovie } from './movie';
import { MoviesService } from './movies.service';
import { IPopular } from './popular';
import { HttpClient } from '@angular/common/http';
import { MovieDetailComponent } from '../movie-detail/movie-detail.component';

@Component({
  selector: 'app-movies',
  templateUrl: './movies.component.html',
  styleUrls: ['./movies.component.css']
})
export class MoviesComponent implements OnInit {
  moviesList: IPopular[] = [];
  movie: IMovie;
  selectedMovie: IMovie;

  constructor(private _moviesService: MoviesService) { }

  ngOnInit() {
    this._moviesService.getPopularMovies()
      .subscribe(moviesList => {
        this.moviesList = moviesList;
      },
        error => console.log(error)
      );

  }

  onSelect(movie: IMovie): void {
    this.selectedMovie = movie;
    window.setTimeout(function() {window.scrollTo(0, 5000); }, 300);
  }
}

Parent HTML

<div>
  <ul class="movies" *ngFor="let movie of moviesList.results">
    <li [class.selected]="movie === selectedMovie" (click)="onSelect(movie)">
      <img class="poster" [src]="'https://image.tmdb.org/t/p/w200/'+ movie.poster_path">
      <br> {{movie.title}} 
    </li> 
  </ul>
</div>

<app-movie-detail [movie]='selectedMovie'></app-movie-detail>

IMovie Interface Definition

export interface IMovie {
    vote_count: number;
    id: number;
    video: boolean;
    vote_average: number;
    title: string;
    popularity: number;
    poster_path: string;
    original_language: string;
    original_title: string;
    genre_ids: number[];
    backdrop_path: string;
    adult: boolean;
    overview: string;
    release_date: string;
}

IPopular Interface Definition

 import { IMovie } from './movie';

export interface IPopular {
    results: Array<IMovie>;
    page: number;
    total_results: number;
    dates: DateTimeFormat;
    total_pages: number;
}

Child Component Details

import { Component, OnInit, Input, OnChanges } from '@angular/core';
import { IResult } from './result';
import { IVideo } from './video';
import { IMovie } from '../movies/movie';
import { MovieDetailService } from './movie-detail.service';
@Component({
  selector: 'app-movie-detail',
  templateUrl: './movie-detail.component.html',
  styleUrls: ['./movie-detail.component.css']
})
export class MovieDetailComponent implements OnChanges {

  @Input() movie: IMovie;

  videoList: IVideo[] = [];
  video: IResult;

  constructor(private _moviedetailService: MovieDetailService) { }

  ngOnChanges() {
    this._moviedetailService.getTrailer(this.movie.id)
      .subscribe(videoList => {
        this.videoList = videoList;
      },
        error => console.log(error)
      );
  }

  ScrollToTop(): void {
    window.setTimeout(function() {window.scrollTo(5000, 0); }, 300);
  }
}

Child HTML Details

<body class="background" [background]="'https://image.tmdb.org/t/p/original'+ movie.backdrop_path" *ngIf="movie">
  ...
...

Upon implementing these codes, an ERROR message stating "TypeError: Cannot read property 'id' of undefined" is encountered.

ERROR TypeError: Cannot read property 'id' of undefined
    at MovieDetailComponent.ngOnChanges (movie-detail.component.ts:22)
...

Any suggestions on how to resolve this issue?

Answer №1

One possible reason for this issue could be that the selectedMovie variable is only defined once a movie is clicked on. To address this, you can prevent the display of the movie details component if no movie has been selected yet:

<app-movie-detail *ngIf="selectedMovie" [movie]="selectedMovie"></app-movie-detail>

Answer №2

Execute a response when Angular resets data-bound input properties. The function will be passed a SimpleChanges object containing current and previous property values.

Remember to wrap your code in a conditional statement: if(this.movie) {...}

ngOnChanges() {
  if(this.movie) {
    console.log(this.movie.id)
  }
}

The ngOnChanges() method will trigger again whenever there are changes to input properties.

Answer №3

When the child component is initialized, the this.movie information is not yet available. This is because, according to your logic, movie details are only accessible when a movie is selected in the parent component, resulting in the undefined error.

In order to avoid this issue, the service call within ngOnChanges should only be made when movie details are indeed available. You can update the ngOnChanges function in the child component like so:

ngOnChanges() {
if (this.movie) {
 this._moviedetailService.getTrailer(this.movie.id)
  .subscribe(videoList => {
    this.videoList = videoList;
  },
    error => console.log(error)
  );
}

}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilizing Node modules in TypeScript, Angular 2, and SystemJS: A Comprehensive Guide

In the process of developing a simple Angular 2 application, I am constructing a class named User. This class includes a function called validPassword() which utilizes the bcrypt library to validate user passwords: import { compareSync, genSaltSync, hashS ...

Troubleshooting connectivity issues between Entities in microORM and Next.js

While trying to run my Next.js application in typescript, I encountered the following error: Error - ReferenceError: Cannot access 'Member' before initialization After consulting the documentation at https://mikro-orm.io/docs/relationships#relat ...

The default selected item in Material Select does not function properly on the second attempt

Is there a way to reset an Angular Material Select Component to its default value after manually changing it on the UI screen? It seems to work fine during initialization but not after manual changes. I am attempting to create a button that will revert th ...

What is the best way to get my Discord bot to respond in "Embed" format using TypeScript?

I've been attempting to create a bot that responds with an embedded message when mentioned, but I'm running into some issues. Whenever I run this code snippet, it throws an error in my terminal and doesn't seem to do anything: client.on(&apo ...

Attempting to incorporate adaljs within TypeScript code

I am currently in the process of building an application using Angular2 and TypeScript. I have come across the need to incorporate ADALJS into my project. Since ADALJS only supports Angular1, I have decided to utilize just adal.js for this particular task. ...

Get the most recent two files from a set

I am currently facing a challenge in retrieving the first 2 documents from a collection in google cloud firestore. My current approach involves using the timestamp of the latest document and then calculating the time range to fetch the desired documents. l ...

Using MobX to alter observed observable values outside of actions is not permitted in combination with Ant Design components

When trying to upload files to the server and receive a response, I encountered an issue. If I override the onChange property of the Upload component (from antd), mobx starts throwing errors and the file uploading process gets stuck in the 'uploading& ...

When attempting to showcase an image within an Angular form, the error message "Form control with unspecified name attribute lacks a value accessor" is displayed

I have a scenario where I am overlaying icons on an image within my ngForm. The goal is to allow users to drag the icons and save their new location when the form is submitted. Everything works as expected, but I encounter a pesky error whenever the page l ...

The exit code 1 was triggered in the npm-lifecycleindex.js file at line 285,

0 silly lifecycle <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="bac9ced5c8d194c9cadbfa8b948a948a">[email protected]</a>~build.prod: Args: [ '/d /s /c', 10 silly lifecycle 'gulp build.prod --color --en ...

What is the best way to retrieve the value from a Material UI textfield after hitting the enter key

Having trouble retrieving input values with the provided code. Attempted using onKeyUp, onKeyDown, and onKeyPress, but none of them returned the value as desired. Typically, I would use the onChange property to get the value, but it triggers for every ne ...

Node corrupting images during upload

I've been facing an issue with corrupted images when uploading them via Next.js API routes using Formidable. When submitting a form from my React component, I'm utilizing the following functions: const fileUpload = async (file: File) => ...

Error encountered in TypeScript's Map class

When working with TypeScript, I keep encountering an error message that reads "cannot find name Map." var myMap = new Map(); var keyString = "a string", keyObj = {}, keyFunc = function () {}; // assigning values to keys myMap.set(keyString, "val ...

Enigmatic Cartography Classification

In my attempt to construct a specialized Map-like class that maps keys of one type to keys of another, I encountered a challenge. A straightforward approach would be to create a Map<keyof A, keyof B>, but this method does not verify if the member typ ...

Guide to implementing a Page Object Model for improved debugging of Protractor tests

Introduction I am on a mission to streamline my e2e testing code using the Page Object Model for easier maintenance and debugging. My Approach When embarking on creating end-to-end tests with Protractor, I follow these steps to implement the Page Object ...

What could be causing issues with my Angular and Express.js Server-Sent Events implementation?

Objective: Implement Server-Sent Events in Angular App with Express Backend Issue: Client does not receive Server-Sent Events Backend Implementation router.get('/options/:a/:b/:c', async (req, res) => { console.log('options endpoint c ...

Issue with missing support-v4.jar in Nativescript Angular

I'm currently testing out a groceries sample using Nativescript with Angular and Typescript. I followed the instructions from this link Encountering the following error: FAILURE: Build failed with an exception. * What went wrong: An issue occurre ...

Warning in TypeScript: TS7017 - The index signature of the object type is implictly assigned as type "any"

An alert for TypeScript warning is popping up with the message - Index signature of object type implicitly has any type The warning is triggered by the following code block: Object.keys(events).forEach(function (k: string) { const ev: ISumanEvent ...

Manually Enroll Node Module

Question: I am tackling a challenge in my TypeScript project where I need to interact with multiple APIs that are not available locally on my computer, but exist on the web. The code compiles without issues on my local machine as I have all the API declar ...

TS2339: The 'map' property is not available on the 'Object' type

I'm currently working with the following code snippet: import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/op ...

Secure your React TypeScript applications with GraphQL authentication

When users try to log in on my website, I need to verify their authentication using data from a GraphQL API. I referred to this tutorial for guidance: https://www.apollographql.com/docs/react/networking/authentication/ In my GraphQL playground, I execute ...