Angular 7 - A collection of Observables containing arrays of nested Observables for a specific Object

Currently, I am facing an issue with displaying articles on my main page from an array in my article-service class. The requirement is to display the articles in groups of three per row. To achieve this, I have created an array of arrays containing three articles each. Each article should be clickable and route to articles/article:id when clicked. However, the problem arises when clicking on an article redirects to the specified route but fails to display the article content.

Upon refreshing the browser at localhost:4200/articles/1, the attributes of the article with id=1 are displayed correctly. Nevertheless, if I navigate from localhost:4200/blog to localhost:4200/articles/1 by clicking an article, nothing is shown.

Below is the structure of the Article class:

export class Article {
    id: string;
    title: string;
    briefInfo: string;
    topic: string;
    author: string;
    authorImg: string;
    relatedArticlesId: string[];
    mainImg: string;
    bodyHtml: string;
    date: string;

    constructor() {

    }
}

Article-Service class implementation:

arrayGroupedBy3: Article[][] = [];

getArticlesGroupedBy3(): Observable<Article[][]> {
    if (this.articles.length > 3) {
      while (this.articles.length > 0) {
        this.articles.map( ( ): Article[] => {
          return this.articles.splice(0, 3);
        }).forEach( item => this.arrayGroupedBy3.push(item));
      }
    }
    return of(this.arrayGroupedBy3);
  }

getArticleById(id: string): Observable<Article> {
  return of(this.articles.find(item => item.id === id));
}

Implementation in Article-list component:

articlesOf3$: Observable<Article[][]>;
selectedId: string;

  constructor(private articleService: ArticleService, private router: ActivatedRoute ) {
  }
ngOnInit() {
  this.getArticles();
}

getArticles() {
   this.articlesOf3$ = this.router.paramMap.pipe(
     switchMap( params => {
       this.selectedId = params.get('id');
       return this.articleService.getArticlesGroupedBy3();
    }));
}

In the article-list.component.html file:

<section class="row content_articles">
  <article class="center_content">

    <ul *ngFor="let listOf3articlesMax of articlesOf3$ | async" 
      class="row content_list articles">
      <li *ngFor="let article of listOf3articlesMax" 
        [class.selected] = "article.id === selectedId"
        class="{{article.topic}}">
        <a [routerLink]="['/articles',article.id]">
          <figure class="row article_img">
            <img src="{{article.mainImg}}" alt="" title="">
          </figure>
          <div class="row content_information">
          <!--Tag-->
            <span class="content_tag">{{article.topic}}</span>
            <div class="row content_text">
              <h4>{{article.title}}:</h4>
              <p>{{article.briefInfo}}</p>
            </div>
          </div>
          <div class="row author_information">
            <figure>
              <img src="{{article.authorImg}}" alt="" title="" />
            </figure>
            <div class="author">
              <h5>by {{article.author}}</h5>
              <span class="date">{{article.date}}</span>
            </div>
          </div>
        </a>
      </li>
    </ul>
</article>
</section>

Content of the article.component.ts file:

  article: Article;
  article$: Observable<Article>;

  constructor(
    private articleService: ArticleService,
    private route: ActivatedRoute,
    private location: Location,
    ) { }


  ngOnInit(): void {
    this.getArticleById();
  }

  getArticleById(): void {
    this.article$ = this.route.paramMap.pipe(
      switchMap((params: ParamMap) => this.articleService.getArticleById(params.get('id'))));

  }
  goBack(): void {
    this.location.back();
  }

Lastly, the code snippet for article.component.html:

<section *ngIf="article$" class="row content_blog_detail {{article$.topic}}">
<div class="row content_article">
        <!--Tag-->
        <span class="content_tag">{{article$.topic}}</span>
        <!--Titles-->
        <h1 class="row">{{article$.title}}</h1>
        <h2 class="row">{{article$.briefInfo}}</h2>

        <!--Return-->
        <a (click)="goBack()" class="btn_return">Back</a>
</div>
</section>

Configuration in app-routing module:

const routes: Routes = [
  {path: 'blog', component: ArticleListComponent},
  {path: 'articles/:id', component: ArticleComponent}
];

The current setup successfully displays a list of three articles per row. However, upon selecting an article to view its details, none of the article information gets displayed. This navigation issue needs to be resolved.

Answer №1

Your content$ property is an Observable. It's important to subscribe to it first before accessing the content object's properties in your Content Component.

Utilize Angular's async pipe for displaying the Content:

<section *ngIf="content$ | async as content" class="row detailed_content {{content.topic}}">
<div class="row article_content">
        <!--Tag-->
        <span class="tag_content">{{content.topic}}</span>
        <!--Titles-->
        <h1 class="row">{{content.title}}</h1>
        <h2 class="row">{{content.description}}</h2>

        <!--Return-->
        <a (click)="navigateBack()" class="btn_back">Go Back</a>
</div>
</section>

Check out the StackBlitz demonstration

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

What is causing the error when using Interfaces and Observable together?

I created a ToDoApp and integrated Firebase into my project, but I am encountering an error. ERROR in src/app/todo-component/todo-component.component.ts(25,7): error TS2740: Type 'DocumentChangeAction<{}>[]' is missing the following proper ...

Remove the icon that indicates severity in PrimeNG

Is there a way to eliminate the X icon from the page? <p-message severity="error" text="*" *ngIf="!form.controls['name'].valid "> </p-message> ...

Attempting to incorporate NestJS modules into an NX monorepo is a task that Angular is currently

Recently, I encountered a frustrating issue while working with a monorepo that contains both Angular and NestJS. In an attempt to access DTOs, I made the mistake of including NestJS files on the client side. This caused Angular compilation errors due to de ...

Utilizing Typescript Decorators to dynamically assign instance fields within a class for internal use

I am interested in delving into Typescript Decorators to enhance my coding skills. My primary objective is to emulate the functionality of @Slf4J from Project Lombok in Java using Typescript. The concept involves annotating/decorating a class with somethin ...

After upgrading from Angular 13 to 14, the <app-root> component is failing to load. Despite no noticeable changes, the issue persists

Having upgraded my Angular 13 app to version 14, I encountered an issue where the page no longer loads properly. Despite checking the configuration and stripping down the index.html file to its basics, the issue persists - nothing seems to be working. Upo ...

What is the best way to display multiple items on a single page using the Ant Design (NG-Zorro) carousel component?

Hey there, I'm looking for a way to display multiple items per page using the ant design (NG-Zorro) carousel. I found some information on their website here: What I'm aiming for is to have something like this - Multiple Items If you have any i ...

Instructions for utilizing a specific router-outlet within a main router-outlet:

I have a main router-outlet within my side-nav component, and I have created two additional router-outlets inside it. This is the structure: router-outlet (main) { router-outlet name='info' { } router-outlet name='servic ...

Unexpected lint errors are being flagged by TS Lint in Visual Studio Code out of nowhere

After a 5-week break from VS Code and my computer due to vacation, I was surprised to see TS lint errors popping up out of nowhere. These errors were completely incorrect and appearing in files that had previously been error-free. It's as if the linte ...

Navigate to a new tab using this.router.navigate

Is there a way to redirect the user to a specific page with ${id} opening in a new tab, after clicking a button in an angular material dialog box? I want to leave the dialog box open while querying the new page. Currently, the redirect happens but not in a ...

the form control values are null or have not been filled in

I am encountering an issue in my .ts file where I cannot retrieve the value of my form control; it is always null. The form consists of two simple controls: Start Date and End Date. I am attempting to extract the values of these dates in my backend .ts fil ...

Triggering the detection of changes even when the value linked to remains the same

I'm facing an issue with a component that is supposed to react to changes in input controls by reformatting the input and removing certain characters. If the removed character corresponds to the previous value, the component fails to detect any change ...

Explaining the distinction between include and rootDir in tsconfig.json

According to the information provided, include defines an array of filenames or patterns that are to be included in the program during the compilation process. On the other hand, rootDir specifies the path to the folder containing the source code of the ap ...

Having trouble with image loading in NextJS after replacing an old image with a new one?

I have been attempting to swap out my current banner with different images to test if they work, but every image I try leads to an error when using next/image or even a simple <image> tag. The error message states that "The requested resource isn&apo ...

Testing Ag Grid's column headers using Jest and Angular CLI has proven challenging, as some columns from columnDefs remain elusive

Currently, I am using Jest and Angular Cli testing to validate column headers. In my attempt to replicate the process outlined on https://www.ag-grid.com/javascript-grid-testing-angular/#testing-grid-contents, I have encountered an issue where only 2 out ...

How do I find the location of /typings when upgrading from version 0.x to 1.x?

As I develop an Angular 2 app using TypeScript, I have been following the guidance found in the 5 Min Quickstart guide. Recently, the npm typings package was updated from version 0.x to 1.x. Following the instructions on the official website, I deleted the ...

Utilize Angular Guards and RxJS to coordinate the flow of data between parent and child Guards. Ensure that the Child Guard waits for the parent

Is it possible to validate data in a child component's guard that was fetched from the parent's guard? I have parent components with employees and used a guard to fetch data from the server. Now, I want to verify this data in the child component& ...

Tips for leveraging the functions service in Next.js for better code reusability

I am just starting to learn Next.js and I have a preference for organizing my API functions in a separate folder called services. I attempted to implement some code based on this topic but unfortunately, it did not work as expected. It seems like my api fu ...

Encountering an issue while trying to import the instanceMethods function within Sequelize

In a file, I have written a function and exported it like this: export function foo(params...) { // do something } When initializing the model, I imported the function in the following manner: import { foo } from "../path/..." instanceMethods: { foo ...

Debug errors occur when binding to computed getters in Angular 2

Currently, I am integrating Angular 2 with lodash in my project. Within my model, I have Relations and a specific getter implemented as follows: get relationsPerType() { return _(this.Relations) .groupBy(p => p.Type) .toPairs() ...

Retrieving an array of objects from a JSON file using Angular 2

I am encountering an issue where the class is not filled properly in an object obtained from a JSON array, resulting in an 'undefined' error. Here is the code snippet for retrieving the object: getFeatures() { return this.http.get('h ...