A comprehensive guide on displaying data in Angular using an API

I have encountered an issue while trying to display data from an API in the 'home.component.html'. Although my 'home.component.ts' successfully fetches the data from the service, I'm facing difficulty rendering it in 'home.component.html'. It seems like I might be handling the data incorrectly.

The error message I receive is: Error: Error trying to diff '[object Object]'. Only arrays and iterables are allowed.

Here is a snippet of my 'home.component.html':

<div class="wrapper">
    <mat-card class="example-card" *ngFor="let data of datas; index as i">

        <mat-card-header>
            <div mat-card-avatar class="example-header-image"></div>
            <mat-card-title>{{ data.attributes.name }}</mat-card-title>
            <mat-card-subtitle>{{ data.attributes.publishedAt | date:'medium' }}</mat-card-subtitle>
        </mat-card-header>
        
        <img mat-card-image [src]="data.attributes.image.data.attributes.url" alt="meme">

    </mat-card>
</div>

And here is an excerpt from my 'home.component.ts':


import { Component, OnInit } from '@angular/core';
import { DataService } from 'src/app/services/data.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {


  datas:any=[];
  errores:string="";
  totalLength:any;

  constructor(private data: DataService) { 
  }

  ngOnInit(): void {

    this.data.getMemes().subscribe(res=>{

     const myJSON = JSON.stringify(res); 
  
     this.datas = myJSON;

     this.totalLength = res.length;

    }, error =>{
      console.log(error);
        if(error.status == 0){
            this.errores="Código del error: "+error.status+" \n Ha ocurrido un error del lado del cliente o un error de red.";
        }else{
            this.errores="Código del error: "+error.status+"\n\n"+error.statusText;
        }
    })  

  }

}


The error displayed in the browser console:

https://i.sstatic.net/MOFHZ.png

This is the structure of the JSON data returned by the API response, containing an array named 'data' with three objects:


{
  "data": [
    {
      "id": 1,
      "attributes": {
        "name": "black",
        "createdAt": "2023-01-17T19:18:29.362Z",
        "updatedAt": "2023-01-17T19:50:47.247Z",
        "publishedAt": "2023-01-17T19:37:56.037Z"
      }
    },
    {
      "id": 2,
      "attributes": {
        "name": "jennie",
        "createdAt": "2023-01-17T19:49:28.235Z",
        "updatedAt": "2023-01-17T19:51:07.573Z",
        "publishedAt": "2023-01-17T19:49:33.399Z"
      }
    },
    {
      "id": 3,
      "attributes": {
        "name": "pink",
        "createdAt": "2023-01-17T19:50:31.818Z",
        "updatedAt": "2023-01-17T19:50:56.444Z",
        "publishedAt": "2023-01-17T19:50:32.786Z"
      }
    }
  ],
  "meta": {
    "pagination": {
      "page": 1,
      "pageSize": 25,
      "pageCount": 1,
      "total": 3
    }
  }
}

Finally, this is my 'data.service.ts':


import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { environment } from 'src/environments/environment.prod';



@Injectable({
  providedIn: 'root'
})
export class DataService {

  REST_API: string ='http://localhost:1337/api/memes';

  httpHeaders = new HttpHeaders().set('Content-Type', 'application/json');

  constructor(
    private http: HttpClient
  ) {  }

  getMemes():Observable<any> {

    let API=this.REST_API;
    return this.http.get(API,{headers:this.httpHeaders}).pipe(
      map((data:any) => { 
        return data;
      }), catchError( error => {
        return throwError(error);
      })
    );

  }



}


Answer №1

What is the reason for attempting to convert JSON.stringify to an array object:

const myJSON = JSON.stringify(res);
this.datas = myJSON;

It is unnecessary to stringify the "res" object, simply pass res.data directly :

this.datas = res.data;

Also, please be aware that your res object does not contain a "length" property :

this.totalLength = res.length

You can achieve the desired result like this:

this.totalLength = res.meta.pagination.total:

Additionally, there seems to be an incorrect property call in your HTML view as the image property is not present in data.attributes:

<img mat-card-image [src]="data.attributes.image.data.attributes.url" alt="meme">

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

Unexpected Token E encountered in the Twitter stream.on function

I'm currently in the process of setting up a search button on my web application that will pull all Twitter tweets related to the search input using the streaming API. Below is my client-side code: <form class="navbar-form navbar-left" role="sear ...

Is there a way to incorporate logic into my Angular routes?

I am looking to secure certain routes within 'case' sections based on the dependency of $scope variables (whether forms are valid or not). var loginForm = angular.module('loginForm',[ 'ngRoute', 'stepsControllers&apo ...

Issue: The 'loopback' module is not found in the NodeJS environment

I can't seem to solve the issue I'm experiencing. Error: Module 'loopback' not found These are the dependencies listed in my package.json file: "loopback": "^3.19.0", "loopback-boot": "^2.6.5", "loopback-component-explorer": "^6.0. ...

Developing a MEAN-based calendar application that is constantly monitoring for updates

I am considering developing a calendar web app to enhance my web development skills. After carefully planning the structure and technologies, I have decided to use the MEAN stack. However, I have encountered a challenge: I want the angular front-end to a ...

Minimizing repeated autofocus calls in material-ui's <TextField> component

In the realm of coding with material-ui, when dealing with the <TextField> component, it's important to keep in mind that the solution may actually lie within React itself. Let's paint a scenario where we're crafting a basic login for ...

Hide elements forever once the form is submitted

I'm seeking help to figure out how to make certain elements disappear after a form submission on my website's dashboard page. Specifically, I need to hide three elements once the user has submitted a form. Elements that need to be hidden: .vc_t ...

My Next.js app's iframe is being blocked by Chrome. Any suggestions on how to resolve this issue?

I have encountered an issue while trying to display an iframe in my Next.js application. Although the iframe is functioning properly in Firefox, it is being blocked in Chrome. The process of rendering the iframe seems straightforward. Below is the comple ...

It seems like the recent upgrade to yarn 2 has caused issues with typescript types, whereas the installation of the same project with yarn 1 was

Recently, I've been attempting to update a typescript monorepo to utilize yarn 2, but I've encountered an issue where typescript is struggling to recognize certain react props. This functionality was working fine in yarn 1.x, leading me to believ ...

Steps for selectively targeting and updating a group of properties in a TypeScript class

Is there a way to consolidate this code into one function that can handle all the tasks below? I'm adding more text here to meet the requirements and hoping for a solution. Thank you! TypeScript is an amazing language that differs slightly from JavaS ...

Can TypeScript be used to dynamically render elements with props?

After extensive research on SO and the wider web, I'm struggling to find a solution. I have devised two components, Link and Button. In short, these act as wrappers for <a> and <button> elements with additional features like chevrons on t ...

What is the best method to determine the current scroll position using JavaScript?

Presently, I am focusing on implementing scroll to top button functionality. The button appears when the content is scrolled to the bottom. My goal is to store the last position when the scroll to top button is clicked so that the user can return to that ...

Combining two arrays by finding common elements

Currently, I am working on a project where I retrieve data from the server, and each piece of data has to adhere to a specific format: const DATA = [ { title: {title: 'Main dishes'}, data: [ {_id: 1, type: 'Pizza'}, ...

Discovering the initial element in an array that meets a condition by employing an asynchronous function

I'm facing a rather peculiar issue. I need to locate the first element in an array that meets a certain condition, but the find function must be labelled as async because a promise is required for the search. Just to clarify, the code provided below ...

Utilizing Mirth Connect to insert XML data into a MySQL database using JavaScript

I am completely new to working with Mirth, JavaScript, and MySQL. I have successfully set up a channel in Mirth to read a text file and convert it to XML. Everything is functioning properly so far. I also attempted to send the XML data to a MySQL databas ...

In my React JS project, I am using an <Add /> component on two distinct pages. However, I am encountering an issue where only one of the pages is correctly receiving the add count prop

I could use some assistance in understanding why the logic for my counter button is not functioning properly on one specific instance. My aim is to have the count displayed by the counter look like this: https://i.sstatic.net/VdJ8o.png In order to add it ...

What is the best way to deliver HTML and JavaScript content using Node.js from virtual memory?

Situation I'm currently developing an in-browser HTML/JS editor, utilizing memory-fs (virtual memory) with Webpack and webpack-html-plugin to package the files created by users in the editor. Storing the files in virtual memory helps avoid I/O operat ...

Stranger things happening when incorporating a generator function in React

Here's a simplified version of my component. It includes a generator function that cycles through values. const App = () => { const [state, setState] = useState("1") function* stateSwitch () { while (true){ yield "2" yield "3" ...

Having issues with $emitting not working for parent-child components in Vue. Any ideas on what I might be doing incorrectly?

I have a login component that I need to call in the main vue component of App.vue. Within the login vue, when I click on any button, it should activate another vue component using Vue.js router to replace the login page. I have searched for solutions but h ...

Cypress: harnessing the power of regular expressions within jQuery selectors for the ":contains()" method

Trying to use Cypress along with a regular expression to target an element that includes specific text. The following get() function successfully works: cy.get('[data-cy=tile]').contains(new RegExp(myVar)) However, the following command does no ...

The URL for this page is not within the app's designated domains and will not open Facebook Dialogs (FB UI)

I am currently working on integrating Facebook UI Dialogs into my website. My goal is to add custom actions when users share a post from my site. I have created my app, added the app URL and domain (which is the same as the URL), and included all necessa ...