1

I subscribed to emitter and I can see the output of this.productNumber in console. but it is not visible in the html file. I am using it like {{productNumber}} in html file.

constructor(private http : HttpClientService) {
        this.http.orderDetailEmitter.subscribe((response)=>{
          this.productNumber=response;

        console.log("productNumber"+this.productNumber);
        });
       }

HTML file

<div>
          <div class="mat-display-1">you have {{productNumber}} product</div>
          <mat-form-field floatLabel="never" appearance="legacy" color="accent">


              <mat-label> Name</mat-label>

              <input matInput required>
              <mat-hint align="end">min 5 characters</mat-hint>

            </mat-form-field>
        </div>

enter image description here

please let me know if need more details

code for service

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { EventEmitter } from '@angular/core';

export class Employee{
  constructor(
    public empId:string,
    public name:string,
    public designation:string,
    public salary:string,
    public isEditable : boolean
  ) {}
}

@Injectable({
  providedIn: 'root'
})
export class HttpClientService {
  orderDetailEmitter = new EventEmitter<number>();


  constructor(
    private httpClient:HttpClient
  ) {

     }

     getEmployees()
  {

    return this.httpClient.get<Employee[]>('http://localhost:8081/fetchEmployees');
  }

  public deleteEmployee(employee) {
    return this.httpClient.delete<Employee>("http://localhost:8081/deleteEmployee" + "/"+ employee.emailid);
  }

  public createEmployee(employee) {
    return this.httpClient.post<Employee>("http://localhost:8081/employees", employee);
  }

  public updateEmployee(employee){
    return this.httpClient.post<Employee>("http://localhost:8081/updateEmployee", employee);
  }

  public createUser(user){
    return this.httpClient.post("http://localhost:8081/registration",user);
  }


}
sparsh610
  • 1,552
  • 3
  • 27
  • 66

2 Answers2

2

The issue is that your emitter emits before your template is ready. The EventEmitter is basically just a Subject and doesn't emit again if you subscribe. Thereby, the EventEmitter should technically only be used in an angular Component or Directive in combination with and @Output

In your code I do not see you emit anything in your orderDetailEmitter, but I guess this is something that needs to be replayed amongst subscribers. You should use a ReplaySubject for such a thing:

export class HttpClientService {
  readonly orderDetailEmitter = new ReplaySubject<number>(1);

  //...
}

The 1 as parameter indicates that a next subscriber should only receive the last emitted value of the stream.

Poul Kruijt
  • 69,713
  • 12
  • 145
  • 149
  • I am using the default change detection strategy. but not sure how can i use the above code `this.productNumber = this.http.orderDetailEmitter;`. could you please help – sparsh610 Apr 07 '20 at 19:21
  • I guess the `orderDetailEmitter` is an Observable. So if you assign it to productNumber, this will become that observable and you can pass it to the `async` pipe – Poul Kruijt Apr 07 '20 at 19:23
  • I made it like this `productNumber; constructor(private http : HttpClientService) { this.productNumber=this.http.orderDetailEmitter; }` – sparsh610 Apr 07 '20 at 19:28
  • we are not subscribing it, so do we will get the response ? – sparsh610 Apr 07 '20 at 19:30
  • the `async` pipe takes care of that – Poul Kruijt Apr 07 '20 at 19:46
  • Reading replaysubject for first time. Let me check it in detail. Is there any need to change other code ? – sparsh610 Apr 07 '20 at 20:33
  • @sparsh610 no that's all. You can use the async pipe if you want. This way you don't have to unsubscribe when the component is destroyed. Otherwise you get memory leaks and double subscriptions when you revisit the component – Poul Kruijt Apr 07 '20 at 21:02
  • now I am facing issue with code `this.http.orderDetailEmitter.emit(this.matBadgeNumber);`.as now I cannot emit it – sparsh610 Apr 07 '20 at 21:11
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/211165/discussion-between-sparsh610-and-pierreduc). – sparsh610 Apr 07 '20 at 21:13
  • @sparsh610 that's because a `ReplaySubject` is from rxjs which uses `next()` instead of `emit`. If you check the source code of angulars EventEmitter than the `emit()` is nothing more than a `next()` :) – Poul Kruijt Apr 08 '20 at 06:22
1

The constructor fires to early. Move initialization code out of the constructor and into ngOnInit() for things your template depends on.

  1. Implement OnInit in the component.
  2. Create a function called ngOnInit() and put the subscribe code there.

Example:

export class MyComponent implements OnInit {

  // keep the constructor for dependency injection only
  constructor(
    private httpClient:HttpClient
  ) {}

  ngOnInit() {
     this.http.orderDetailEmitter.subscribe((response)=>{
        this.productNumber=response;

        console.log("productNumber"+this.productNumber);
      });
  }

  ...
Jeff
  • 103
  • 4
  • Try setting productNumber to a static value. productNumber = 5. Does that value show in the template? – Jeff Apr 07 '20 at 21:56