Display Specific Detail When Click View Button in Angular 4

3.8k views Asked by At

i need help in making this "view detail function" work. First, i had the users component which i want to imitate on how it worked. Like you have to access its service when you try to get the specific thing. But the users component is its not from coming from an api. Now, i want to imitate it in my news component which the details is coming from an api. How can i access the specific things details of the news component? I've put the code below both on the users component and news component.Thanks for the help.

user.service.ts

import { User } from './user.model';
import { Subject } from 'rxjs/Subject';
export class UserService {

usersChanged = new Subject<User[]>();

  private users: User[]= [
    new User('Harry', 'James', 99999889),
    new User('Thomas', 'Baker', 99638798)
  ];

  getUsers() {
    return this.users.slice();
  }

  getUser(index: number) {
    return this.users[index];
  }

user-list.component

import { Component, OnInit } from '@angular/core';
import { User } from '../user.model';
import { UserService } from '../user.service';
import { Router, ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-user-list',
  templateUrl: './user-list.component.html',
  styleUrls: ['./user-list.component.css']
})
export class UserListComponent implements OnInit {

  users: User[];
  index: number;

  constructor(private userService: UserService, private router: Router, private route: ActivatedRoute) { }

  ngOnInit() {
      this.users = this.userService.getUsers();
      this.userService.usersChanged
      .subscribe(
        (users: User[]) => {
          this.users = users;
        }
      );
  }

  onViewUserDetail(index: number){
    this.router.navigate(['users', index]);
  }

news.service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders} from '@angular/common/http';
import 'rxjs/add/operator/map';

@Injectable()
export class NewsService {
    constructor(private httpClient: HttpClient) {
  }

getNews() {
    const authToken = localStorage.getItem('auth_token'); 
    const headers = new HttpHeaders() 
    .set('Content-Type', 'application/json') 
    .set('Authorization', `Bearer ${authToken}`);

    return this.httpClient
      .get('sample/news', { headers: headers })
      .map(
        (response => response));
}


getNewsDetail(index: number) {
    //
  }

news-list.component.ts

import { Component, OnInit } from '@angular/core';
import { NewsService } from '../news.service';
import { Router, ActivatedRoute } from '@angular/router';


@Component({
  selector: 'app-news-list',
  templateUrl: './news-list.component.html',
  styleUrls: ['./news-list.component.css']
})
export class NewsListComponent implements OnInit {
  newslists: any;
  constructor(private newsService: NewsService, private router: Router, private route: ActivatedRoute) { }

  ngOnInit() {

    this.newsService.getNews()
      .subscribe(
        (data:any) => {
          console.log(data);
          this.newslists = data.data.data;
          console.log(this.newslists);
        },
        error => {
          alert("ERROR");
        });
  }

  onViewNewsDetail(id: number){
    console.log(id);
    this.router.navigate(['news', id]);
  }

}
2

There are 2 answers

1
Joseph On BEST ANSWER

I did this.

getAllNews() {

    if(this.newslist != null) {
      return Observable.of(this.newslist);
    } 

    else {
      const authToken = localStorage.getItem('auth_token'); 
      const headers = new HttpHeaders() 
      .set('Content-Type', 'application/json') 
      .set('Authorization', `Bearer ${authToken}`);

      return this.httpClient
        .get('samplei/news/', { headers: headers })
        .map((response => response))
        .do(newslist => this.newslist = newslist)
        .catch(e => {
            if (e.status === 401) {
                return Observable.throw('Unauthorized');           
            }

        });
    }
  }


  getNews(id: number) { 
    return this.getAllNews().map((data:any)=> data.data.data.find(news => news.id === id)) 
  }
9
JayDeeEss On

Didn't quite understand what the issue is. You are navigating to detail view onView***Detail() method. If you have defined your routes right, it should go to the respective component. And in that detail component ngOnInit() you can subscribe to the paramMap of the activated route and call the api or get the value from the store, however you want.

ngOnInit() {
        this.paramSubscription = this.route.paramMap
            .switchMap((params: ParamMap) => this.userService.getUser(+params.get('id')))
            .subscribe(
            res => {
                this.user= <User>res;
            },
            err => console.log('error retreiving user detail')
            )

    }

you will have the details in the user property in your detail component, and you can display it however you want it to be.

Update

To get detail for your news, you can create a news store with a behavior subject that will call you service to get all news - the list. your component can call this store as well. This store will expose getter of your private behavior subject which expose it as Observable.

Then you can access the subjects value at ny time by getValue() and don't have to call the api again for any view detail call. See example below:

    @Injectable()
    export class NewsStore {
        private _news: BehaviorSubject<List<News>> = new BehaviorSubject(List([]));

        constructor(
            private newsService: NewsService) {
            this.loadInititalData();
        }

        get news() {
            return this._news.asObservable();
        }

    getNews(id: number): any {
            return this._news.getValue().filter(news=> news.id == id);
        }

loadInititalData() {
        this.newsService.getAll()
            .subscribe(
            res => {
                let news= res;
                this._news.next(List(news))
            },
            err => this.handleError(err, "loadinitialdata")
            );
    }
    }