Issue with Angular 11: A stream was anticipated but instead an improper object was provided. Acceptable options are Observable, Promise, Array, or Iterable

I'm well aware that there are numerous questions with similar titles and issues. I've dedicated the past day and a half to reading and experimenting with potential solutions, but unfortunately, none have worked for me. My situation varies slightly, and I am using a newer version of Angular.

The challenge I am facing involves implementing pagination for data displayed on a chart (built using chart.js through ng2-charts). Below is the code snippet showcasing how it currently looks:

<div class="paginable-area" [class.loading]="chartLoading">
    <app-line-chart *ngIf="!tableError" [lineChartData]="chartData" [lineChartLabels]="chartLabels"></app-line-chart>
    <div class="page-controls">
        <button class="button" (click)="previousChartPage()" [disabled]="currentChartPage <= 1">◀</button>
        <button class="button" (click)="nextChartPage()">▶</button>
    </div>
</div>

Upon initial page load, the first page displays correctly and appears as expected. However, upon clicking the button to view another page, an error is triggered in the console:

TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
    RxJS 13
    Angular 16
    RxJS 30
    getAggregates dashboard.component.ts:144
    nextChartPage dashboard.component.ts:92
    DashboardComponent_Template_button_click_9_listener dashboard.component.html:10
    Angular 22
    DashboardComponent_Template dashboard.component.html:10
    Angular 13
    RxJS 3

Upon clicking the "Next Page" button, the following methods are invoked in sequence:

 public nextChartPage(): void {
      this.currentChartPage += 1;
      this.getAggregates();
  }

// ...

private getAggregates(): void {
    // Code logic
}

// ... 
// Additional code snippets

The getAggregates() method is called each time a new chart page is requested, including the initial chart loading. The first call succeeds, but subsequent calls encounter errors and result in empty objects being returned.

I have a table on the same page displaying data from the same API and paginated in the same manner, without any issues. The problem most likely lies within the map() function, but I have been unable to pinpoint it.

  • I have verified all imports and ensured there are no incorrect rxjs internal import statements.
  • I have attempted to isolate the source of the error by systematically commenting out portions of the pipe operations without success.
  • Trying different return methods using rxjs's of() has led to nested Observables instead of expected results.

Being relatively new to Angular and rxjs, I suspect there might be mistakes in my implementation. Any assistance or guidance would be greatly appreciated.

EDIT: After modifying the service method, the error message changed when attempting to load the next page of the chart. The current error indicates:

TypeError: r.map is not a function
    getAggregateStats stats.service.ts:75
    RxJS 9
    Angular 16
    RxJS 28
    getAggregates dashboard.component.ts:143
    nextChartPage dashboard.component.ts:92
    DashboardComponent_Template_button_click_9_listener dashboard.component.html:10
    Angular 22
    Dashboar... 

Something indicates that while the initial pipe operation functions as intended, consecutive calls receive a non-array response, causing the absence of a map() function. Yet, inspecting the console output reveals the correct content in the second request!

// First request, upon page load:
GET https://my-api.xxx/stats?page=1    [HTTP/1.1 200 OK 249ms]
[{"successful":"1","unsuccessful":"1","day":"2020-12-15"},{"successful":"1","unsuccessful":"0","day":"2020-12-14"}]


// Second request, requesting the next page
GET https://my-api.xxx/stats?page=2    [HTTP/1.1 200 OK 249ms]
{"2":{"successful":"2","unsuccessful":"1","day":"2020-12-11"},"3":{"successful":"3","unsuccessful":"6","day":"2020-12-10"}}

Answer №1

After some investigation, it became clear that the issue was unrelated to Angular or Typescript (despite the unhelpful error message).

The results I was receiving from the API were sourced from a Laravel (PHP) backend. It appears that the format of the data returned on subsequent pages caused confusion:

[
  "0" => ["some" => "data"],
  "1" => ["some" => "more data"],
]

When converted to JSON, this looks like:

[
  {"some": "data"},
  {"some": "more data"}
]

However, the format on the PHP side for the second page and onwards looked like this:

[
  "2" => ["some" => "data"],
  "3" => ["some" => "more data"],
]

Although it seemed correct as the indexes incremented, Laravel's array-to-JSON conversion resulted in:

{
  "2": {"some": "data"},
  "3": {"some": "more data"}
}

This unexpected change disrupted Angular's workflow.

I apologize for anyone who had to go through all this explanation. The lesson learned is to approach PHP with caution.

Answer №2

I've encountered similar issues numerous times, but using ngIf always comes to the rescue. Make sure to pass data to the chart only when it's available.

<app-line-chart *ngIf="!tableError && chartData.length > 0" [lineChartData]="chartData" [lineChartLabels]="chartLabels"></app-line-chart>

Answer №3

Personally, my problem stemmed from the fact that the http api receiving the get requests was not functioning properly.

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

Storing Data in Angular: Tips for Saving Entire Page or Component Data for Future Use

I have developed an Angular 6 application with multiple components that utilize @angular/material's horizontal stepper. Each step within the stepper contains complex forms, some created using template driven forms and others using formgroups. I am loo ...

Troubleshooting Standalone Component Routing Issues in Angular 16

For my Angular 16 project code, visit this link To create the Angular 16 project with routing enabled, I used the following command: ng new myapp --standalone Then, I added other components using: ng g c components/home The boilerplate files are differe ...

Angular model remains static when incorporated within the document.addEventListener() attribute

Can anyone help me figure out why my attempt to update the model name this.name on click inside document.getElementById('source-selection').addEventListener is not working? Surprisingly, a simple alert within that function does trigger successful ...

I cannot pinpoint the reason behind the strange offset on my page

<div> <div> <span class="card-title">New Item Form</span> </div> <form (ngSubmit)="onSubmit()" class="col s6"> <div class="row"> <div class="input-field col s6"> <input type="te ...

Leveraging es6-promise in conjunction with TypeScript 2.1 and ES5 Webpack for streamlined async/await functionality

Utilizing es6-promise with TypeScript version 2.1.1 that targets ES5 and webpack in my project has presented some challenges. app.ts import "es6-promise/auto"; export class Foo { bar() : Promise<string>{ return Promise.resolve("baz"); ...

How can you dynamically display a 'Show More' button for overflow content in Angular 2, and switch it to 'Show Less' when clicked?

My current challenge involves implementing a solution in Angular 2. The task at hand is to have a button appear only when the content within a div overflows. When clicked, the button should switch to 'Show Less' and hide excess content upon subse ...

Tips for ensuring old logs do not display on Heroku Logs

I'm puzzled as to why my heroku logs command keeps showing old logs. Attempting to resolve this issue, I tried: heroku drains heroku logs However, the logs still display outdated information: app[api]: Release v1 created by user <a href="/cdn-c ...

Upon the initial render, the fetch request in the NextJS Client component is not triggered

When I load my home page, I want to display a collection of cards from a client component. However, the API fetch request in the client component does not trigger on the initial render, preventing the cards from appearing. To fix this issue, I have to manu ...

Angular Directive causing the generation of redundant elements

I am facing an issue with my Angular directive where it seems to be generating duplicate button and ul elements with the class "dropdown" after each specified element. The directive works perfectly when implemented using plain JavaScript. Can anyone identi ...

The parameter 'string | JwtPayload' cannot be assigned to the parameter 'string'

Utilizing Typescript alongside Express and JWT for Bearer Authorization presents a specific challenge. In this situation, I am developing the authorize middleware with JWT as specified and attempting to extricate the current user from the JWT token. Sampl ...

Using Try...catch compared to .catch

Within my service.ts file, I have various user service functions that handle database operations. export const service = { async getAll(): Promise<User[]> { try { const result = await query return result } catch (e) { rep ...

How can I upload multiple images in one request using Typescript?

HTML: <div> <input type ="file" (change)="selectFiles($event)" multiple="multiple" /> </div> Function to handle the change event selectFiles(event) { const reader = new FileReader(); if (event.target.files & ...

The Radio Button's value appears in a distinct way on Ionic Angular

I am currently working with the Ionic framework and I am trying to display data values on radio buttons. However, I am facing difficulties in retrieving the correct value and setting it appropriately. index.html <td> <label>{{learn ...

Changing routes in Angular causes the @input value to update

Working with Angular 8, I have a setup with two components: the parent component and the child component. The parent component needs to pass an object or string when the URL parameters change. In the parent component, I implemented this code snippet that ...

The absence of class generic parameter constraints cascades down to class properties

Trying to implement TypeScript with TypeORM using a generic class has been challenging. The issue lies within my AbstractDal which takes a generic parameter that is constrained to extend IEntity. IEntity is supposed to have an id property, yet for some rea ...

Mastering Data Labels in ng2-chart: A step-by-step guide

Once again, I find myself battling my Angular and JavaScript challenges, each question making me feel a little less intelligent. Let me walk you through how I got here. In my most recent project, I wanted to enhance the user experience by incorporating sl ...

Fetching data from one component to load an Angular component

Essentially, I have a grid within Ionic that dynamically populates its rows using ngFor. Each row contains an ionic button labeled "View details" which, when clicked, should display all the data associated with that specific object. Imagine it as a preview ...

Tips for navigating to a different route during the ngOnInit lifecycle event

How can I automatically redirect users to a specific page when they paste a URL directly into the browser? I would like users to be directed to the /en/sell page when they enter this URL: http://localhost:3000/en/sell/confirmation Below is the code I am ...

Restrict the frequency of requests per minute using Supertest

We are utilizing supertest with Typescript to conduct API testing. For certain endpoints such as user registration and password modification, an email address is required for confirmation (containing user confirm token or reset password token). To facilit ...

Time taken for a webpage to finish loading

Is there a way to programmatically obtain the page load time in an Angular application? Situation: On my dashboard page, various components are making multiple calls. I want to calculate the overall time it takes to load all widgets on the page. ...