Generate an array of objects by combining three separate arrays of objects

There are 3 private methods in my Angular component that return arrays of objects.

I want to combine these arrays into one array containing all the objects, as they all have the same class.

Here is the object structure:

 export class TimelineItemDto {
    id: any;
    creatorAvatarUrl: string;
    categoryName: string;
    creatorName: string;
    subcategoryName: string;
    description: string;
    type: string;
}

Below is the code for the component:

export class HomeComponent implements OnInit {

  constructor(private _router: Router, private http: HttpClient) { }

  color: ThemePalette = 'primary';
  classes: TimelineItemDto[] = [];
  requests: TimelineItemDto[] = [];
  courses: TimelineItemDto[] = [];
  timelineItems: TimelineItemDto[] = [];
  checked = false;
  disabled = false;

  ngOnInit(): void {
    const token = localStorage.getItem('jwt');
    if (!token) {
      this._router.navigate(['/main/login']);
    }

    this.getTimelineItems();
  }

  getCourses(): any {
    return this.http
      .get(environment.baseUrl + '/Course/GetCourses')
      .subscribe((data: TimelineItemDto[]) => {
        return data;
      });
  }

  getClasses(): any {
    return this.http
      .get(environment.baseUrl + '/Class/GetClasses')
      .subscribe((data: TimelineItemDto[]) => {
        return data;
      });
  }

  getRequest(): any {
    return this.http
      .get(environment.baseUrl + '/Requests/GetRequests')
      .subscribe((data: TimelineItemDto[]) => {
        return data;
      });
  }

  getTimelineItems(): any {
    var courses = this.getCourses();
    var classes = this.getClasses();
    var requests = this.getRequest();
    this.timelineItems = [...classes, ...courses, ...requests];
    console.log(this.timelineItems);
  }
}

At this line

this.timelineItems = [...classes, ...courses, ...requests];
, I encounter the following error:

core.js:4197 ERROR TypeError: classes is not iterable

How can I resolve this issue?

Answer ā„–1

The Issue

Let's examine the code snippet below

  getCourses(): any {
    return this.http
      .get(environment.baseUrl + '/Course/GetCourses')
      .subscribe((data: TimelineItemDto[]) => {
        return data;
      });
  }

The code above utilizes the .get() method followed by the .subscription() method. This reveals that the function actually yields a subscription rather than an Observable. Therefore, attempting to iterate over this subscription results in an error.

Resolution

To address this issue, there are multiple approaches available. Below is my proposed solution:

  • Fetch classes as Observable
  • Retrieve requests as Observable
  • Obtain courses as Observable
  • Merge these 3 Observables into a single Observable
  • Subscribe to the new Observable

Refer to the following revised code

   constructor(private _router: Router, private http: HttpClient) {}
  color: ThemePalette = "primary";
  timelineItems: TimelineItemDto[] = []
  getCourses = () =>
    this.http.get<TimelineItemDto[]>(
      environment.baseUrl + "/Course/GetCourses"
    );

  getClasses = () =>
    this.http.get<TimelineItemDto[]>(environment.baseUrl + "/Class/GetClasses");

  getRequest = () =>
    this.http.get<TimelineItemDto[]>(
      environment.baseUrl + "/Requests/GetRequests"
    );

  classes$: Observable<TimelineItemDto[]> = this.getClasses();
  requests$: Observable<TimelineItemDto[]> = this.getRequest();
  courses$: Observable<TimelineItemDto[]> = this.getCourses();
  timelineItems$: Observable<TimelineItemDto[]> = combineLatest([
    this.classes$,
    this.courses$,
    this.requests$
  ]).pipe(
    map(([classes, courses, requests]) => [...classes, ...courses, ...requests])
  );
  checked = false;
  disabled = false;
  ngOnInit(): void {
    const token = localStorage.getItem("jwt");
    if (!token) {
      this._router.navigate(["/main/login"]);
    }

    this.getTimelineItems();
  }

  getTimelineItems(): any {
    this.timelineItems$.subscribe({
      next: (items) => this.timelineItems = items
    })
  }

View this solution on stackblitz

Answer ā„–2

To understand how asynchronous data operates, it is essential to refer to this source for detailed information on async data handling.

In essence, one must await the emission of data by the source. In this scenario, waiting for the RxJS observables to emit values before attempting to assign them is crucial. Moreover, when subscribing to multiple observables, utilizing the RxJS forkJoin function can trigger requests concurrently.

export class HomeComponent implements OnInit {
  constructor(private _router: Router, private http: HttpClient) { }

  color: ThemePalette = 'primary';
  classes: TimelineItemDto[] = [];
  requests: TimelineItemDto[] = [];
  courses: TimelineItemDto[] = [];
  timelineItems: TimelineItemDto[] = [];

  checked = false;
  disabled = false;
  ngOnInit(): void {
    const token = localStorage.getItem('jwt');
    if (!token) {
      this._router.navigate(['/main/login']);
    }

    this.getTimelineItems();
  }

  getTimelineItems(): any {
    forkJoin(
      <Observable<TimelineItemDto[]>>this.http.get(environment.baseUrl + '/Class/GetClasses'),
      <Observable<TimelineItemDto[]>>this.http.get(environment.baseUrl + '/Course/GetCourses'),
      <Observable<TimelineItemDto[]>>this.http.get(environment.baseUrl + '/Requests/GetRequests')
    ).subscribe({
      next: ([classes, courses, requests]) => {
        this.classes = classes;
        this.courses = courses;
        this.requests = requests;
        this.timelineItems = [...classes, ...courses, ...requests];
        console.log(this.timelineItems);
      },
      error: error => {
        console.log('handle error');
      }
    });
  }
}

It is advisable to review the aforementioned link. The variable this.timelineItems may remain empty when accessed outside the subscription since it might not have been assigned values yet.

In simple terms, this.timelineItems is only accessible within the subscription scope.

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

Preserve component state in Angular 4 by saving it when navigating to a different component

Currently, I am faced with a challenge while developing an application using Angular. In one component, users can input data into three selectboxes and then initiate a search to find matching results. Upon clicking on a match, they are taken to another com ...

Retrieve user information by their unique user ID from a MongoDB database using a Node, Express, and TypeScript API

Currently, I am working on a Node JS and Express with TypeScript API project. In this project, I need to retrieve data stored by a specific user from MongoDB based on their user ID. This is a snippet from my DataRouter.ts: router.get('/:userId', ...

Is it possible to transform all values in arrays to 0s in JavaScript/p5.js during the copying process?

Iā€™m struggling with a simple code where I want to store an array of arrays containing FFT audio data. It seems like there might be a JavaScript issue because when I try to push the array into another array called spectrums, all the values inside spectr ...

Validation of Date in Angular 5 (with specified minimum and maximum dates)

Struggling to find a simple solution for this issue, I have a date input like the following: <input [(ngModel)]="toolDate" type="text" class="tool_input tool_input__date"> To control the input and restrict it to only accept dates, I am using . In m ...

Encountering a JavaScript Error: "e is null" while utilizing assert for checking JavaScript alert text

I encountered a javascript alert in my program that I was able to interact with by reading the text and clicking on the buttons. However, when I tried to verify the alert text using assertequals function, I faced an error. Here is the code snippet: String ...

TypeORM's Polymorphic Relationship fails to retrieve data from the parent entity

Currently, I am utilizing https://github.com/bashleigh/typeorm-polymorphic for handling polymorphic relations in my model. There are several models involved: // Device Entity @Entity() @TableInheritance({ column: { type: 'varchar', name: 'ty ...

Flipping json stringify safety

In my NextJS React application, I encountered an issue with circular references when using getInitialProps to fetch data. Due to the serialization method used by NextJS involving JSON.stringify, it resulted in throwing an error related to circular structur ...

Implementing AJAX to dynamically update information based on user's selection from a dropdown

I need to dynamically adjust the opacity of my graph bars without requiring the user to manually refresh the page. I'm considering using AJAX for this purpose. How can I implement this functionality? const opacitySlider = document.getEle ...

Uploading multiple files simultaneously in React

I am facing an issue with my React app where I am trying to upload multiple images using the provided code. The problem arises when console.log(e) displays a Progress Event object with all its values, but my state remains at default values of null, 0, and ...

Encountering an error while running npm install - package.json data parsing failed

Encountering an error during npm install on Windows 10, using node v6.10.3 and npm v3.10.10 Please assist in resolving this issue. Error message: npm ERR! npm v3.10.10 npm ERR! file C:\angular2-helloworld\package.json npm ERR! code EJSONPARSE ...

The functionality of Node.js middleware is not functioning correctly

My module contains Routes, and I want to verify access before allowing users to proceed. Within the Routes module, there are two routes and two access-check functions that I want to use as middlewares: const checkUser = (req, res, next) => { if (!us ...

Clicking on an icon to initiate rotation (Material UI)

Is there a way to toggle the rotation of an icon (IconButton) based on the visibility of a Collapse component? I want it to point down when the Collapse is hidden and up when it's shown. const [expanded, setExpanded] = useState<boolean>(false); ...

No styles are appearing on a specific element after running a specific jQuery function on that element within a Vue page

I recently integrated JQuery-AsRange (https://github.com/thecreation/jquery-asRange) into my vue.js project. Everything functions as expected within the .vue page, however, I am facing an issue with css styling not being applied. The css styles should be ...

Transforming FormData string key names into a Json Object that is easily accessible

Recently, I encountered an issue where my frontend (JS) was sending a request to my backend (Node Typescript) using FormData, which included images. Here is an example of how the data was being sent: https://i.stack.imgur.com/5uARo.png Upon logging the r ...

Developing Angular components with nested routes and navigation menu

I have a unique application structure with different modules: /app /core /admin /authentication /wst The admin module is quite complex, featuring a sidebar, while the authentication module is simple with just a login screen. I want to dyn ...

Issue encountered where Moment locale functionality is working in local development environment, but not functioning properly in the

My application built with Next.js requires displaying the date in Bengali instead of English. The issue arises after running the build command 'build:next build' where the production version displays the date in English (e.g. '20 January, Su ...

Make leaflet function operate synchronously

There seems to be an issue with calling the setMarker() function within another function, as the markers are not being set. It's possible that this is due to the asynchronous nature of the setMarker() function because of the Promise it uses. getCities ...

successful callback after passport registration

router.post('/register', function(req, res, next){ var name = req.body.name; var email = req.body.email; var username = req.body.username; var password = req.body.password; var password2 ...

What is the method for extracting a value that is being displayed beneath a text in a React component using Selenium?

Attached is a screenshot showcasing HTML tags: Our task is to display the 3 within react-text. Here's the code snippet I attempted: WebElement MyText = driver.findElement(By.xpath("(//div[@class='badge-number'])[6]")); JavascriptExecut ...

Enable users to choose either today's date or a future date by implementing AngularJS UI Bootstrap

I am currently utilizing the ui-bootstrap directive for a datepicker. My goal is to restrict the selection of dates to today's date or any future dates. Below is the HTML code snippet for the datepicker: <div class="input-group"> ...