XXIV
XXIV

Reputation: 358

How to get id from object in ngFor to be used for id lookup in database (Angular)?

I have a webpage of articles that I grab from my database and put into an array and then display using an ngFor. On each article, I have a 'View Details' button. I want to be able to click that button and then be taken to /articles/{articleId}. I am trying to do that by grabbing the id of the article that is clicked (View Details is clicked on an individual article), but I am not sure on how to grab that id when the button is clicked. I've seen to use the Input and pass the data from parent to child, but I'm not sure how to get that to work when using an ngFor, or if this idea of passing the data is even a good way.My idea currently is to grab the id and then pass it to a child component which then uses my findById function to grab all the data about the article and then show that article in that child component (/article/{articleId}

Child Component:

import {Component, OnInit} from "@angular/core";
import {Article} from "../article.model";
import {ArticlesService} from "../articles.service";
import {ActivatedRoute, Params} from "@angular/router";

@Component({
  selector: 'app-view-articles',
  templateUrl: './view-articles.component.html'
})
export class ViewArticlesComponent implements OnInit {
  article: Article;
  id: string;

  constructor(private route: ActivatedRoute, private articleService: ArticlesService) { }

  // this is where I would used the passed id to pass into findArticle but an id is hardcoded in right now
  ngOnInit() {
    this.articleService.findArticle("59dcba5fae3c751b45665ca7")
        .subscribe(
            (article: Article) => {
              this.article = article;
            }
        );
  }

}

Article Service findArticle function (called from child component)

  findArticle(id: string) {
    return this.http.get('http://localhost:3000/article/' + id)
        .map((response: Response) => {
          const article = response.json().obj;
          let transformedArticle: Article = new Article(article.author, article.title, article.body, article._id);
          return transformedArticle;
        })
        .catch((error: Response) => {
          this.errorService.handleError(error.json());
          return Observable.throw(error.json());
        });
  }

Parent Component

import { Component, OnInit } from '@angular/core';
import {ArticlesService} from "./articles.service";
import {Article} from "./article.model";

@Component({
  selector: 'app-articles',
  templateUrl: './articles.component.html',
  styleUrls: ['./articles.component.css']
})
export class ArticlesComponent implements OnInit {
  articles: Article[];

  constructor(private articleService: ArticlesService) { }

  ngOnInit() {
    this.articleService.getArticles()
        .subscribe(
            (articles: Article[]) => {
              this.articles = articles;
            }
        );
  }

}

Parent HTML

<div class="row">
  <!--/span-->
  <div class="col-6 col-sm-6 col-lg-4"
       *ngFor="let article of articles">
    <h2>{{article.title}}</h2>
    <h4>By: {{article.author}}</h4>
    <p>{{article.body}}</p>
    <p><a class="btn btn-default" href="#">View details »</a></p>
  </div>
</div>

Upvotes: 0

Views: 1879

Answers (2)

Dmitry Grinko
Dmitry Grinko

Reputation: 15212

Articles page:

<a class="btn btn-default" (click)="viewDetails(article.id)">View details</a>

import { Router } from '@angular/router';

viewDetails(_id){
   this.router.navigate(['/article/'], { queryParams: { id: _id } });
}

Article page:

import {Router, ActivatedRoute, Params} from '@angular/router';
import {OnInit, Component} from '@angular/core';
import {ArticlesService} from "./articles.service";
import {Article} from "./article.model";

@Component({...})
export class ArticleComponent implements OnInit {
  article: Article;
  constructor(private activatedRoute: ActivatedRoute) {}

  ngOnInit() {
    this.activatedRoute.params.subscribe((params: Params) => {
        let id = params['id'];
           this.articleService.findArticle(id).subscribe(
               (article: Article) => this.article = article;
           );
      });
  }

}

Upvotes: 1

Andresson
Andresson

Reputation: 1307

You can use routerlinks eg.

<div class="row">
  <!--/span-->
  <div class="col-6 col-sm-6 col-lg-4"
       *ngFor="let article of articles">
    <h2>{{article.title}}</h2>
    <h4>By: {{article.author}}</h4>
    <p>{{article.body}}</p>
    <p><a class="btn btn-default" [routerLink]="['/articles',article.id]">View details »</a></p>
  </div>

and or if you prefare create a function..

goToArticleDetails(id) {
  this.router.navigate(['/articles', id]);
}

Upvotes: 3

Related Questions