The Challenge of Iterating Through an Array of Objects in Angular Components using TypeScript

Could someone please explain why I am unable to iterate through this array? Initially, everything seems to be working fine in the ngOnInit. I have an array that is successfully displayed in the template. However, when checking in ngAfterViewInit, the console.log displays the array but looping through it using "for of" or "forEach" does not yield any results.

import { JobsService } from '../jobs.service';
import {Job} from '../models/Job';

@Component({
    selector: 'app-job',
    templateUrl: 'job.component.html'
})

export class JobComponent implements OnInit, AfterViewInit {
    title = 'Job';
    jobs: Job[] = [];
    InProcess = '';
    CurrentPartner = '';
    ShowProcess = false;
    sended = '';

    constructor(private jobsService: JobsService) {
    }

    ngOnInit() {
        this.jobs = this.jobsService.getJobs();
    }
    ngAfterViewInit() {
      console.log(this.jobs); // The array is shown in the console

      // Looping through the array doesn't work
      this.jobs.forEach((oneJob) => {
        console.log(oneJob);
      });
    }
}

Screenshot of the console in Google Chrome

The content of the service:

import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import {Job} from './models/Job';

interface IJob {
  message: string;
  jobs: any[];
}

@Injectable({
  providedIn: 'root'
})

export class JobsService {
  constructor(private httpClient: HttpClient) { }
  private REST_API_SERVER = 'http://localhost:8080/myband/api/getjobs.php';
  private REST_API_SERVER_SEND = 'http://localhost:8080/myband/api/sendjob.php';
  jobList: Job[] = [];
  errorMessage: any;
  message: string;

  static handleError(err: HttpErrorResponse) {
    let errorMessage = '';
    if (err.error instanceof ErrorEvent) {
      errorMessage = `An error occurred: ${err.error.message}`;
    } else {
      errorMessage = `Server returned code: ${err.status}, error message is: ${err.message}`;
    }
    console.error(errorMessage);
    return throwError(errorMessage);
  }

  public getJobs() {
    this.requestJobs().subscribe(
      iJob => {
        this.message = iJob.message;
        for (const job of iJob.jobs) {
          const oneJob: Job = new Job(job);
          this.jobList.push(oneJob);
        }
      },
      error => this.errorMessage = error as any
    );
    return this.jobList;
  }

  public requestJobs(): Observable<IJob> {
    return this.httpClient.get<IJob>(this.REST_API_SERVER).pipe(
       catchError(JobsService.handleError)
    );
  }
}

Answer №1

First and foremost, I want to emphasize the importance of isolating responsibilities in your code.

Your service should focus on providing a single function: offering a way to access your data. This means that any logic within the getJobs() method can be handled within your component.

export class JobsService {
    constructor(
        private httpClient: HttpClient,
    ) {}
    private REST_API_SERVER = 'http://localhost:8080/myband/api/getjobs.php';

    public requestJobs(): Observable<IJob> {
        return this.httpClient.get<IJob>(this.REST_API_SERVER);
    }
}

With this approach, you have the freedom to manipulate your data within your component.

import { JobsService } from '../jobs.service';

@Component({
    selector: 'app-job',
    templateUrl: 'job.component.html'
})

export class JobComponent implements OnInit, AfterViewInit {
    title = 'Job';
    jobs$;
    InProcess = '';
    CurrentPartner = '';
    ShowProcess = false;
    sent = '';

    constructor(private jobsService: JobsService) {
    }

    ngOnInit() {
        this.jobs$ = this.jobsService.requestJobs();
    }



    ngAfterViewInit() {
        this.jobs$
            .pipe(
                map(() => {}), // modify your data here
                catchError(() => {}) // handle errors here;
            )
            .subscribe(
                () => {} // access your final data here. 
            );
    }
}

Key Points:

  1. You have the option to remove the subscribe() call and utilize the async pipe in your template;

  2. Using the map operator in pipe() is not mandatory – you can work directly with your final data within the initial subscribe() callback.

  3. You can convert an Observable into a Promise by employing the toPromise() method on a single observable. Remember to use async / await within your ngAfterViewInit.

If you need further assistance or clarification, feel free to reach out.

Answer №2

Give this a shot:

Using the Object.keys method to iterate through the jobs object and log each job to the console.

Answer №3

Make sure to replace the below part of your code with an iterator function:

// When looping through the array, nothing is happening
this.jobs.forEach(oneJob, function(value, key) {
    console.log(key + ': ' + value);
});

Using forEach in AngularJS:

To learn more, check out AngularJS forEach Docs

Syntax:

someIterable.forEach(object, iterator, [context])

Answer №4

Take a look at the example provided below

class Position {
    title: any;
    department: any;
    constructor(details: any) {
        this.title = details.title;
        this.department = details.department;
    }
}

let positions = [
    {
        title: "Manager",
        department: "Operations"
    }, 
    {
        title: "Developer",
        department: "Technology"
    }
];

let positionList: any = [];

positions.forEach(p => {
    let role: Position = new Position(p);
    positionList.push(role);
})

console.log(positionList);

positionList.forEach((p: any) => {
    console.log(p);
})

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

Issue with Moment.js: inability to append hours and minutes to a designated time

I have a starting time and I need to add an ending time to it. For example: start=19:09 end=00:51 // 0 hours and 51 minutes I want to add the 51 minutes to the 19:09 to make it 20:00. I've attempted several different methods as shown below, but none ...

Storing Angular files with JBoss caching

My angular 13 application is deployed in a war file on jboss and tomcat application server. Unfortunately, users are facing an issue where they have to forcefully refresh cached files with ctrl+f5 in their browser every time changes are deployed in order t ...

Unable to perform the GET request method due to data indicating [object object]

Currently, I am attempting to use a get request method within both Vue and Express in order to retrieve data based on my v-model. Displayed below is the code where I am trying to send the data to Express. getResult() { axios .get( `${process. ...

My JavaScript array is not working with the stringify function

I am trying to encode my JavaScript array into JSON using stringify. Here is the code: params["margin_left"] = "fd"; params["text"] = "df"; params["margin_to_delete"] = "df"; console.info(params); When I check the output in Chrome console, it shows: [m ...

Adjust the range slider's color depending on its value

I'm looking to customize the color of a range slider as its value increases, switching from red to green. Below is the code I've tried, but it's not quite working as intended. The goal is for the color to change based on the value of masterR ...

Navigating with Node.js: Understanding how to showcase the response data within a list structure

I am brand new to working with node.js and I'm looking to display the data I receive as a response on my webpage. Currently, I can see the output in my console. Is there a way to show this data on my actual page? GET Request: app.get('/bestell_ ...

How can we use Mongoose .find to search with an array stored in req.params and respond with an array containing each value along with its

It would be great if a user could input multiple tags in a search field, and have them separated client-side (before making the .get call) to send over ajax with each keypress. While testing the API with Postman on the server-side, if the .get method retu ...

The offline functionality of the Angular Progressive Web App(PWA) is experiencing difficulties

As per the official guidelines, I attempted to create a PWA that functions in offline mode using pure PWA without angular-cli. However, despite following the official instructions, I was unable to make it work offline. The document in question can be foun ...

Associate a click event to a dropdown menu element to trigger on selection

My issue involves having multiple select elements. When one of them is changed, I am trying to bind a click event only to its next element with the .btn class. Below is the code snippet illustrating my problem: <div class="whole"> <ul> ...

Can the sliding transition effect used in createMaterialTopTabNavigator be implemented in createMaterialBottomTabNavigator as well?

When using createMaterialTopTabNavigator, the transition from screen to screen involves a sliding effect as you press the tabs. On the other hand, createMaterialBottomTabNavigator uses a fading-in animation for its transitions. Is there a way to combine o ...

What's the best way to apply a class to a React element upon clicking it?

I'm currently working on a React component to create a hamburger menu, but I'm struggling to add a class when a button is clicked. I'm fairly new to React, so any gentle guidance would be appreciated. The code below is what I have so far, bu ...

I have to make sure not to input any letters on my digipas device

There is a slight issue I am facing. Whenever I input a new transfer of 269 euros with the bank account number BE072750044-35066, a confirmation code is required. The code to be entered is 350269. https://i.stack.imgur.com/YVkPc.png The digits 350 corres ...

Facing issues with Handsontable opening within a jQuery UI dialog?

After implementing the Handsontable plugin in multiple tables, everything appears as expected on the parent page. However, when attempting to open a dialog containing a table, the tables do not display properly (only in IE). A demonstration of this issue c ...

Having trouble deploying Firebase Cloud function following the migration to Typescript

After following the steps outlined in the firebase documentation to convert my cloud functions project to TypeScript (see https://firebase.google.com/docs/functions/typescript), I encountered an error when attempting to deploy using 'firebase deploy - ...

Preventing Paste Function in Electron Windows

Currently, I am utilizing Electron and attempting to prevent users from pasting into editable content. While paste and match style remains enabled, the functionality is flawless on Mac devices. However, there seems to be an issue on Windows where regular ...

Steps for inserting an item into a div container

I've been attempting to create a website that randomly selects elements from input fields. Since I don't have a set number of inputs, I wanted to include a button that could generate inputs automatically. However, I am encountering an issue where ...

Error message: "Link binding error in knockout collection"

In this example, you'll find my Knockout ViewModel. $(document).ready( function () { var Incident = function (CaseNumber, DateOfIncident, Description) { this.CaseNumber = CaseNumber; this.DateOfIncident = DateOfIn ...

Show various perspectives depending on the circumstances

I am looking for a solution to display a different component if my ngFor loop returns null. <ion-select interface="popover" [ngModel]="selectedKidId"> <ion-option *ngFor="let kid of kids" [value]="kid.id">{{kid.name}}</ion-option& ...

Eliminate the JSON object within jqGrid's posted data

The web page I'm working on features Filters with two buttons that load data for jqGrid when clicked. Clicking 'Filter' generates a postData json object and sends it to the server, which is working perfectly. However, I'm facing an is ...

Identify and handle multiple scenarios in JavaScript without using if statements

I have developed a function that is supposed to evaluate all scenarios and provide an immediate result if one of the cases does not match. const addText = (data, addAlternative) => { return (data !== 'N/T' || data === 0 || data) ? d ...