Search code examples
javascriptangulartypescript

Angular 18 @for returning ERROR TypeError: newCollection[Symbol.iterator] is not a function


I decided to start working in the latest Angular version (Angular 18.1) so far I was working with versions 7 to 14...

I just tried making a lil dummy app to showcase a list of movies...

I made a really basic service that gets some data from an API and show this data in a list in html...

I have decided to use the new @for syntax from the latest angular version but now I am getting this error: ERROR TypeError: newCollection[Symbol.iterator] is not a function

Is this related to new version of nagular or am beeing blind and have overlooked an issue in my code?

EDIT: Console.log works.

Here is the component.ts code:

export class MovielistComponent implements OnInit{
  movies: movie[] = [];
  constructor(
    private movieService: GetMoviesService,
  ) { }
  ngOnInit() {
    this.getMoviesList();
  }

  getMoviesList() {
    this.movieService.getMovies().subscribe(
      data => {
        this.movies = data;
        console.log('Movies: ', this.movies);
      }
    )
  }

}

Here is the html file code:

<ul>
  @for (movie of movies; track movie.attributes) {
    <li>{{ movie.attributes.name }}</li>
  } @empty {
    <li>There are no items.</li>
  }
</ul>

And here is the model.ts code:

export interface movie {
  id: number,
  attributes: {
    name: string,
    imageUrl: string,
    synopsis: string,
    year: string,
    genre: string,
  }
}

As requested here is the API response:

{
    "data": [
        {
            "id": 1,
            "attributes": {
                "name": "The Shawshank Redemption",
                "imageUrl": "https://m.media-amazon.com/images/M/MV5BNDE3ODcxYzMtY2YzZC00NmNlLWJiNDMtZDViZWM2MzIxZDYwXkEyXkFqcGdeQXVyNjAwNDUxODI@._V1_FMjpg_UY1800_.jpg",
                "synopsis": "Over the course of several years, two convicts form a friendship, seeking consolation and, eventually, redemption through basic compassion.",
                "year": "1994",
                "genre": "drama",
                "createdAt": "2024-07-16T12:34:06.769Z",
                "updatedAt": "2024-07-16T12:36:29.952Z",
                "publishedAt": "2024-07-16T12:36:29.951Z"
            }
        },
        {
            "id": 2,
            "attributes": {
                "name": "The Godfather",
                "imageUrl": "https://m.media-amazon.com/images/M/MV5BM2MyNjYxNmUtYTAwNi00MTYxLWJmNWYtYzZlODY3ZTk3OTFlXkEyXkFqcGdeQXVyNzkwMjQ5NzM@._V1_FMjpg_UY1982_.jpg",
                "synopsis": "Don Vito Corleone, head of a mafia family, decides to hand over his empire to his youngest son, Michael. However, his decision unintentionally puts the lives of his loved ones in grave danger.",
                "year": "1972",
                "genre": "crime, drama",
                "createdAt": "2024-07-16T12:36:14.143Z",
                "updatedAt": "2024-07-16T12:36:15.723Z",
                "publishedAt": "2024-07-16T12:36:15.720Z"
            }
        },
        {
            "id": 3,
            "attributes": {
                "name": "The Dark Knight",
                "imageUrl": "https://m.media-amazon.com/images/M/MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw@@._V1_FMjpg_UY2048_.jpg",
                "synopsis": "When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, Batman must accept one of the greatest psychological and physical tests of his ability to fight injustice.",
                "year": "2008",
                "genre": "action, crime, drama, thriller",
                "createdAt": "2024-07-22T09:37:42.564Z",
                "updatedAt": "2024-07-22T09:38:19.346Z",
                "publishedAt": "2024-07-22T09:38:19.343Z"
            }
        }
    ],
    "meta": {
        "pagination": {
            "page": 1,
            "pageSize": 25,
            "pageCount": 1,
            "total": 3
        }
    }
}

Solution

  • You can also add interfaces for the response coming from the API.

    export interface Pagination{
        page: number;
        pageSize: number;
        pageCount: number;
        total: number;
    }
    
    export interface GetMoviesResponse {
        data: movie[];
        meta: Pagination;
    }
    

    You have to access the data property inside the response, which is the array.

    Generally we get this error when we try to use an object on an ngFor or @for ERROR TypeError: newCollection[Symbol.iterator] is not a function

    export class MovielistComponent implements OnInit{
      movies: movie[] = [];
      constructor(
        private movieService: GetMoviesService,
      ) { }
      ngOnInit() {
        this.getMoviesList();
      }
    
      getMoviesList() {
        this.movieService.getMovies().subscribe(
          (data: GetMoviesResponse) => {
            this.movies = data.data; // changed here!
            console.log('Movies: ', this.movies);
          }
        )
      }
    
    }