Using ng2 to retrieve an object from an HttpGet service

I'm currently facing an issue with retrieving JSON data from my WebAPI. Every time I attempt to use the returned object in my component, it displays as undefined.

The goal is to showcase student and course data on the homepage of my website. Currently, my controller / API is returning hardcoded data.

student.service.ts

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/observable/of';

@Injectable()
export class StudentService {
    private http: Http;            

    constructor(http: Http) {
        this.http = http;
    }

    getStudentCourse(): Observable<IStudentCourse> {
        var model: IStudentCourse;

        this.http.get('/api/student/getstudentcourse').subscribe(result => {
            model = result.json() as IStudentCourse;

            console.log(model);            

        }, error => console.log('Could not load data.'));

        console.log("model: outside of httpget: " + model);

        return Observable.of(model);        
    }
}

export interface IStudentCourse {
    refNo: string;
    student: number;
    offeringName: number;
    offeringID: string;
}

I can verify that my service successfully returns JSON data which I can see in Network Traffic and my console.

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

home.component.ts

import { Component, OnInit } from '@angular/core';
import { StudentService, IStudentCourse } from './student.service';

@Component({
    selector: 'home',
    templateUrl: './home.component.html'
})
export class HomeComponent implements OnInit {    

    studentCourse: IStudentCourse;
    Message: string;

    constructor(
        private _studentService: StudentService) {        
    }

    ngOnInit(): void {
        this.getStudentCourse();
        console.log("fromngOnInit");
        console.log("Init: " + this.studentCourse.offeringName);
    }

    getStudentCourse() {        
        this._studentService.getStudentCourse().subscribe(
            item => this.studentCourse = Object.assign({}, item),
            error => this.Message = <any>error);
    }
}

In the screenshot provided, it's evident that studentCourse is consistently null during ngOnInit, making it difficult to bind.

I would greatly appreciate any assistance in resolving this issue. Thank you.

Updated: plnkr Link

To enhance reusability across multiple components, I've chosen to keep this HttpGet service in a separate file.

Answer №1

When you return an Observable of your model that is empty at the moment, it operates asynchronously.

Give this a shot:

fetchStudentCourse(): Observable<IStudentCourse>: {
    return this.http.get('/api/student/getstudentcourse')
        .map(response => response.json() as IStudentCourse)        
        .catch(() => throw 'Failed to fetch data.');

}

Take a look at this plunk

Answer №2

To accomplish this task, consider implementing a BehaviorSubject. In your Http Subscription, trigger the emission of a new value for the Subject.

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Http } from '@angular/http';
import { BehaviorSubject } from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/of';


@Injectable()
export class StudentService {
    private studentCourse: BehaviorSubject<IStudentCourse> = new BehaviorSubject<IStudentCourse>(null);

    public get studentCourse$() { 
        return this.studentCourse.asObservable();
    }

    constructor(private http: Http) { }

    getStudentCourse() {
       this.http.get('https://58cff77fe1a0d412002e446d.mockapi.io/api/student/getstudentcourse/2').map(response => {
         return response.json() as IStudentCourse;
      }).subscribe(course => {
         this.studentCourse.next(course);
      });
    }
}

export interface IStudentCourse {
  id: string,
  refNo: string;
  student: string;
}

Incorporate Angular's async Pipe into your template to automatically subscribe to the Data-holding Observable.

Plunker

Answer №3

Check out the plunker here: plunker

Incorporate the following code into your template:

<h2>Hello {{studentCourse?.student}}</h2>

Avoid subscribing in the service, follow this example instead:

 getStudentCourse(): Observable<IStudentCourse> {
        let model: IStudentCourse;

        return this.http.get('/api/student/getstudentcourse').map(result => {
            model = result.json() as IStudentCourse;
            return model;
        }).catch( error => console.log('Could not load data.'));

    }

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

React Parent Component receiving events triggered by Child Component

How can I capture child events in the parent component? Take a look at my code to see what I am attempting to achieve. Page Component interface PageProps {} const Page: FC<PageProps> = ({}) => { //I want to avoid binding handlers here and instea ...

There is no overload that fits this call (regarding a basic array retrieved from an api)

While attempting to utilize a .map function on a simple array (['a','b','c']) fetched using the useEffect hook, I encountered an error in TypeScript. The array elements rendered correctly when the code was executed and no erro ...

How can you notify a component, via a service, that an event has occurred using Subject or BehaviorSubject?

For my Angular 10 application, I created a service to facilitate communication between components: export class CommunicationService { private messageSubject = new Subject<Message>(); sendMessage(code: MessageCode, data?: any) { this.messag ...

Is it possible to add additional text to an input field without modifying its existing value?

I have a numerical input field labeled "days" that I want to add the text " days" to without altering the actual numerical value displayed. <input type="number" class="days" (keyup)="valueChanged($event)"/> Users should only be able to edit the num ...

What's preventing this function from deducing the type?

I'm currently utilizing the "openapi-typescript" tool to automatically generate all the types based on my swagger server specifications. In this process, I have created a Type called "GetUrls" which contains all the keys associated with the "get" meth ...

Angular2 poses a strange problem with ngClass

It seems like Angular is expecting me to use single quotes for the class names even if there are no hyphens in my CSS class name. I've tried everything but Angular keeps insisting on using hyphens for this specific CSS class... it's strange, or m ...

Exploring subobjects while fetching observables (typescript/angular)

When retrieving JSON from an API into an Angular service, I am working with a collection of objects structured like this: { "data": { "id": 1, "title": "one" }, "stats" : { "voteCount": 8 } } I am particularly interested in the ' ...

Error message: 'Unrecognized element' appears when using a custom Angular library component

I am currently in the process of developing a custom Angular library that will be utilized across multiple projects and eventually published to a private Verdaccio npm registry. While everything seems to work well - from rendering to building - there is o ...

NestJS does not recognize TypeORM .env configuration in production build

Currently, I am developing a NestJS application that interacts with a postgres database using TypeORM. During the development phase (npm run start:debug), everything functions perfectly. However, when I proceed to build the application with npm run build a ...

Is it necessary to configure Webpack or use a plugin to remove console.log() statements by default in an Angular Application, or does it do so automatically?

Welcome to my first post! I hope I can effectively communicate the question and the background that led me to ask it. I am relatively new to web programming, with about 1 and a half years of experience working with Java, JavaScript, and TypeScript using An ...

Determine the data type of an individual attribute within a collection of classes

I am working with a series of classes that have a body property defined within them. Here is an example: class Foo { body: {foo: string} constructor(body: Record<string, string>) { this.body = { foo: body.foo } } } class Bar { body: {ba ...

Tips for querying enum data type using GraphQL

I am having trouble querying an enum from GraphQL in my Nest.js with GraphQL project. I keep getting an error message saying: "Enum 'TraitReportType' cannot represent value: 'EMBEDDED'". I have tried using type:EMBEEDED, but it did not ...

Switch between div elements in Angular 2 while dynamically changing their values depending on a specific condition for displaying or hiding

After referring to the solution found in (Hide/show individual items inside ngFor), I am facing a challenge regarding setting the value of pinMe[j] based on a condition. In my scenario, I need to toggle between div elements while also determining what shou ...

Exploring Ngrx: Leveraging a single selector to choose multiple property modifications

I need some help with my reactive Form Angular application that uses the NGRX store. Instead of subscribing to the entire state, I want to subscribe to changes in specific fields like "name" and "city." I have been attempting to use the selector selectFor ...

Dealing with Nodejs promises can be frustrating, especially when encountering errors, but incorporating the Sequelize ORM can

Currently I am working on developing a web application for nodejs using the popular sequelize ORM and typescript. Here is an example from my code: this.createNewGame(player.idPlayer).then((game) => { this.getBestScore(player.idPlayer).then((bestSc ...

Having trouble invoking the "done" function in JQuery following a POST request

I am currently working on a Typescript project that utilizes JQuery, specifically for uploading a form with a file using the JQuery Form Plugin. However, after the upload process, there seems to be an issue when trying to call the "done" function from JQue ...

Display a slideshow of images using the text and <img> tags found within a string in an Angular application

Currently, I am developing a blog system in Angular that involves utilizing a text editor component (ngx-text-editor) for inserting images and text. These images and text are then saved to the database. However, I am facing an issue when attempting to disp ...

What are the steps for personalizing themes in the Monaco editor?

I'm currently working on a code editor with Monaco. The syntax highlighting in Monaco for Javascript and Typescript only highlights keywords as dark blue, strings as brown, and numbers as light greenish-yellow. My goal is to customize the vs-dark the ...

Resolve the clash between Jest and Cypress within a React application developed using TypeScript

Encountering a conflict in the React app after installing Cypress with TypeScript. Despite trying to resolve it using GitHub solutions, the issue persists. I am sharing all configuration files in hopes that someone can identify the problem. cypress/tsconfi ...

gulp-angular2 task is malfunctioning

Currently, I am in the process of working on a gulpfile and have written the following task: var tsProject = ts.createProject('app/Resources/public/angular/tsconfig.json'); gulp.task('angular-2', function () { var tsResul ...