I'm curious to know how the HomeComponent in my Angular11 application can access the data sent out by the Subject within the DataService

Creating a new service called DataService was necessary to make the data accessible throughout the app. I intended to store the data coming from the API in a Subject. However, despite being able to see the array of objects in a log from the DataService, the array in the HomeComponent that is supposed to receive the data appears as undefined in the console:

browser inspector console output

As a beginner, I suspect there might be some mistakes in my code. Can someone provide assistance?

HomeComponent:

import {Component, OnInit, Output} from '@angular/core';
import {DataService} from '../../shared/services/data.service';
import {Subscription} from 'rxjs';
import {Article} from '../../shared/models/article';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
  @Output() articles?: Article[];
  articleSubscription?: Subscription;
  constructor(private dataService: DataService) { }

  ngOnInit(): void {
    this.dataService.emitArticlesSubject(this.dataService.loadArticles());
    this.articleSubscription =
      this.dataService.articlesSubject.subscribe(
        (articles) => {
          this.articles = articles;
        }
      );
    console.log('HOME COMPONENT: ngOnInit: this.articles : ' + JSON.stringify(this.articles));
  }

}

DataService:

import { Injectable } from '@angular/core';
import {BehaviorSubject, Subject} from 'rxjs';
import {ArticleService} from './article.service';
import {Article} from '../models/article';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  articles?: Article[];
  message = 'No results match your search.';
  articlesSubject = new Subject<Article[]>();
  constructor(private articleService: ArticleService) { }

  emitArticlesSubject(action: any): void {
    this.articlesSubject.next(action);
  }

  loadArticles(): any {
    this.articleService.getAll().subscribe(
      data => {
        this.articles = data._embedded.articles;
        console.log('DataService: loadArticles() : ' + JSON.stringify(this.articles));
      },
      error => {
        console.log('ERROR: DataService not able to loadArticles !' );
      }
    );
  }
  
  loadArticlesByActivity(): any {
    this.articleService.getAllSortedByActivity().subscribe(
      data => {
        this.articles = data._embedded.articles;
      },
      error => {
        console.log('ERROR: DataService not able to loadArticlesByActivity');
      }
    );
  }
}

ArticleService:

import { Injectable } from '@angular/core';
import {HttpClient, HttpHeaders} from '@angular/common/http';
import {Observable} from 'rxjs';
import {Article} from '../models/article';
import {ResponseEntities} from '../../core/ResponseEntities';

const baseUrl = 'http://localhost:8080/articles';
const queryUrl = '?search=';
const dateUrl = '?sort=date,desc';

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

  constructor(private http: HttpClient) { }

  getAll(): Observable<ResponseEntities<Article[]>> {
    return this.http.get<ResponseEntities<Article[]>>(`${baseUrl}${dateUrl}`);
  }

  getAllSortedByActivity(): Observable<ResponseEntities<Article[]>> {
    return this.http.get<ResponseEntities<Article[]>>(`${baseUrl}/${dateUrl}`);
  }

  search(term: string): Observable<ResponseEntities<Article[]>> {
    return this.http.get<ResponseEntities<Article[]>>(`${baseUrl}/${queryUrl}${term}`);
  }

  // Other methods omitted for brevity
}

Answer №1

It seems like the issue might be linked to a subscription problem within the data service.

this.dataService.emitArticlesSubject(this.dataService.loadArticles());

Here, the emitArticlesSubject() function is being called. However, loadArticles() is subscribed to an underlying service. The problem arises because emitArticlesSubject() calls loadArticles() without waiting for its subscription to complete, resulting in undefined articles. One solution could be to use promises in loadArticles() or restructure your services by directly calling ArticleService in your HomeComponent.

Answer №2

Instead of console logging the contents of this.articles in your HomeComponent before they have been fetched, it is recommended to log them after they have been retrieved. To achieve this, you can update your code like so:

this.articleSubscription =
  this.dataService.articlesSubject.subscribe(
  (articles) => {
    this.articles = articles;
    console.log('HOME COMPONENT: Articles Fetched: ' + JSON.stringify(this.articles));
  }
);

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 nested 'each' syntax in Handlebars - not looping through all elements

As a newcomer to the world of Javascript/JSON/Handlebars, I am struggling with getting a JSON object that has two nested levels to function properly within a Handlebars template. I have already confirmed that the JSON object is valid using JSONLint, but I ...

Trouble with parsing JSON in PHP

I've been encountering issues with a PHP script I recently created. The problem lies in my inability to retrieve data from a JSON file named demo.json using PHP. Below is the content of the JSON file: { "checkouts":[ { "billing_address":{ ...

The blender model that was imported into the three.js scene appears to be lacking color

I have created a tree model in Blender and exported it for use in Three.js. However, when I load the model in my scene, it appears only in black and white. Can you advise on the correct method to ensure that the model displays with its original colors? .j ...

Include text into a JSON outline

While there are JSON parsers available, I feel like this task is simple enough to approach it in a DIY manner. std::string item_name; std::string item_address; item_name = "John"; item_address = "New York"; {"item": {"name": "std::cout << item_nam ...

Show the number of users currently online on your website by pulling in data from

I need to extract the "current / max Players" data from a specific website: My goal is to show only the player count, such as "70 / 175", on another webpage and have it automatically update whenever someone visits my .html page (which I can switch to .php ...

Angular2 integration with Nativescript footbar

I'm a newcomer to Nativescript UI and I'm looking for guidance on how to add a footer in Nativescript with angular2. Currently, I am working on designing a page with tabs where I need to display a list view and a footer on one of the tabs. The l ...

Use `$$state: {…}` within the request rather than the data

When attempting to send a request with data, I am only getting "f {$$state: {…}}" in the console. $scope.createTask = function () { var req = $http.post('api/insert', { title: $scope.newTitle, description: ...

Problem arising from apostrophe usage in Javascript OData request

In my current project, I have a text input field that passes a value through JS to fetch filtered data of names from a JSON file using OData query parameters. However, I've encountered an issue where if a name contains an apostrophe, it results in a ...

The <table mat-table> element seems to be failing to display any content

I'm currently developing an app that showcases user information, and I'm using the angular/materials library to create a table. However, I'm encountering an issue where the mat-table isn't displaying the column titles. I've attemp ...

Using keyvalue pipe in Angular to iterate over objects through inserted loops

My Customized Answer import { Question } from './question'; export class Answer { AnswerId: number; Content: string; IsCorrect: boolean; Mark: number; QuestionId: number; Question: Question; } My Personal TestStartComp ...

Is there a tool in Node.js to set up a new project, similar to the scaffolding feature in Visual Studio for C# projects

Is there a way to efficiently create a node.js project with TypeScript and Express, and embed an SPA client using React and Redux templates written in TypeScript as well? Is there a scaffolding tool available to streamline this process, similar to the ea ...

The feature of declaration merging does not function properly with the express 4.17.* request type

Looking to enhance the Request type, I decided to create a folder @types/express. Within this folder, I included a file index.d.ts with the following content. namespace Express { interface Request { user: number; } } Upon referencing req.user in V ...

Eliminate repeated elements from an array using Typescript

I am a novice when it comes to TypeScript, and I have been encountering challenges applying my JavaScript skills. Specifically, could someone assist me in converting the JavaScript code provided below into TypeScript? If direct conversion is not feasible, ...

Setting a timer in NGRX to control the interval between two actions

I am currently working with Angular and NGRX, and I have a requirement to implement a timer between two actions. The timer should start when the first action is triggered and stop when the second action occurs. I need to be able to store this timer in a gl ...

Unraveling JSON - blank outcome, devoid of any errors

My decoding process seems to hit a roadblock when trying to retrieve values from the container in the init method without any error messages. Any idea what I might be overlooking? func getUserInfo(userId: Int, completion: @escaping (User?, Error?) -&g ...

What is the proper way to utilize mapped types in TypeScript module declarations?

How can I create a type declaration for an external module and use a mapped type for this declaration? Currently, the module appears as: declare module "deferred-regl"{ import { Regl } from 'regl' type IDregl<T> = { setRe ...

Save the Angular HTML code of components in a database and display them as individual components

I have a project where users can edit and add Angular Component code in HTML & TS format. When I use the HTML code on the view, it works correctly and shows the Angular Component. However, when retrieving it from the SQL database, only the text is displaye ...

The Angular (click) event requires two clicks in order to trigger the associated Typescript function

I'm facing an issue with a Typescript function that I've linked to (click) in my HTML. Oddly, I have to click the button twice for the function to be executed. Interestingly, if I don't provide any parameters, the function works as expected ...

js TouchEvent: When performing a pinch gesture with two fingers and lifting one of them up, how can you determine which finger was lifted?

I am currently working on a challenging touching gesture and have encountered the following issue: let cachedStartTouches: TouchList; let cachedMoveTouches: TouchList; function onStart(ev: TouchEvent) { // length equals 2 when two fingers pinch start ...

Can you please explain the process of implementing server-side rendering with React?

During my work, I utilized Node's express for sever side rendering with React. However, an unexpected error occurred as shown below. ^ SyntaxError: Unexpected token '<' This particular error popped up unexpectedly. I reached ou ...