Vineel Pellella
Vineel Pellella

Reputation: 422

Unable to use provide data for other component using service

I created two components one for listing all loans and another is for viewing each loan details on click of each card in the list. When I tried to console the data in subscribe, I can view the information, but I am not getting any data on the HTML page.

loan.ts

export class Loan
{
    id :number;
    title: string;
    description: string;
    amount: number;
}

list-loan-component.ts

import { Component, OnInit } from '@angular/core';
import * as EventEmitter from 'events';
import { Loan } from '../loan';
import { LoanService } from '../loan.service';

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

  constructor(private loanService: LoanService) { }

  ngOnInit(): void {
    this.loans = this.loanService.getLoans();
  }

  openLoan(loan: Loan)
  {
    this.loanService.loan.emit(loan);   
  }
}

list-loans-component.html

<div class="container">
    <div class="card-deck">
       <div *ngFor="let loan of loans">
           <div class="card" routerLink="/loan/view" routerLinkActive="active"
           (click)="openLoan(loan)">
               <div class="card-header"> {{loan.title}} - {{loan.amount}}</div>
               <div class="card-body">
                   <p class="card-text">{{loan.description}}</p>
               </div>
           </div>
       </div>
    </div>
</div>

view-loan.component.ts

import { ChangeDetectorRef, Component, Input, OnChanges, OnInit } from '@angular/core';
import { ActivatedRoute, ActivatedRouteSnapshot, Params } from '@angular/router';
import { Loan } from '../loan';
import { LoanService } from '../loan.service';

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

  selectedLoan: Loan ;

  constructor(private loanService: LoanService, private router:ActivatedRoute) { }

  ngOnInit() {
    this.loanService.loan.subscribe(loan =>
      {
        this.selectedLoan = loan;     
      }
    );
  }
}

view-loan.component.html

<div class="card text-center">
  <div class="card-header">
    {{selectedLoan['title']}}
  </div>
  <div class="card-body">
    <h5 class="card-title">Loan From :  {{selectedLoan['title']}}</h5>
    <h3 style="text-align: left; text-decoration: underline;">Details:</h3>
    <p class="card-text">{{selectedLoan['description']}}</p>
    <p class="card-text">{{selectedLoan['amount']}}</p>
    <a href="#" class="btn btn-primary">Go somewhere</a>
  </div>
  <div class="card-footer text-muted">
    2 days ago
  </div>
</div>

loan.service.ts

import { Injectable, Output, EventEmitter } from "@angular/core";
import { Loan } from "./loan";
    
@Injectable({
    providedIn: 'root'
  })
export class LoanService
{
    loan = new EventEmitter<Loan>();

    private loans:Loan[] = [
        {
            "id":1,
            "title" : "HDFC Credit Loan",
            "description" :"Loan to clear all credit card payments",
            "amount" : 24958.23
        },
        {
            "id":2,
            "title" : "Aditya birla personal Loan",
            "description" :"Loan to personal expenses",
            "amount" : 12000.00
        }
    ]

    constructor(){}

    getLoans(): Loan[]{
        return this.loans.slice()
    }

    getLoan(id:number): Loan{
        this.loans.forEach(loan =>
            {
                if(loan["id"] === id) 
                    return loan;
            }
        );
        return new Loan();
    }
}

Note: I am using routing as well. Kindly let me know if routing can cause any of this issues.

Upvotes: 1

Views: 113

Answers (3)

Inside your list-loans-component.html you are iterating over your loans like so:

<div *ngFor="let loan of loans | async"> but your loans are not a async value, as your loan service directly returns an Loan[] (not Observable<Loan[]>). Just remove the async pipe and things will start to work.

p.s. Very well asked question.

Edit:

Here is a working stackblitz with your code line for line.

Upvotes: 0

Anton Marinenko
Anton Marinenko

Reputation: 2982

It seems you have EventEmitter value passed before your ViewLoanComponent is loaded. Just replace your EventEmitter for ReplaySubject, like this:

export class LoanService
{
    $loan = new ReplaySubject<Loan>(1);
...

And next in code

openLoan(loan: Loan)
  {
    this.loanService.$loan.next(loan);   
  }

Also remove the async pipe, in your case:

<div *ngFor="let loan of loans">

Upvotes: 1

Saghi Shiri
Saghi Shiri

Reputation: 617

You just can using async pipe on an observable but in your code you are using on loans[] witch is an array.

Remove the pipe.

But I recommend to use a BehaviorSubject or an Observable rather than an EventEmitter. https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service

Upvotes: 0

Related Questions