0

I am trying to call a component from another component, I am calling a method of that component, the method is called without any issue, but the view of that component is not refreshing, below is a demo code to show what I am trying to do.

myFirstComponent.component.ts

ngOnInit() {
        this.secondComponent = new SecondComponent();
        this.secondComponent.showValues(5)
}

second-component.component.ts

ngOnInit() {
       this.value = 10;    
       this.showValues(this.value)     
}

showValues(value: any) {
        this.newValue = value;
        console.log('This is console value' + this.newValue)
} 

In my HTML,

New Value is {{newValue}}

Output when first time the component will be loaded will be

New Value is 10
 //in console it will be This is console value 10

Output when the showValues is called from first component

New Value is 10
// in console it will be, This is console value 5

So variable value gets updated but it is not reflecting on the UI, my second component will not be refreshed ever, is this even a good practice to work with, or is there any other way by which I can achieve this? Thank You.

shrey shah
  • 91
  • 2
  • 11

1 Answers1

2

Passing data or invoking methods between sibling component

When passing data between components, I find the RxJS `BehaviorSubject` very useful.

You can also use a regular RxJS Subject for sharing data via a service, but here’s why I prefer a BehaviorSubject.

  1. It will always return the current value on subscription - there is no need to call onNext().
  2. It has a getValue() function to extract the last value as raw data.
  3. It ensures that the component always receives the most recent data.
  4. you can get an observable from behavior subject using the asObservable() method on behavior subject.
  5. Refer this for more

Example

In a service, we will create a private BehaviorSubject that will hold the current value of the message. We define a currentMessage variable to handle this data stream as an observable that will be used by other components. Lastly, we create the function that calls next on the BehaviorSubject to change its value.

The parent, child, and sibling components all receive the same treatment. We inject the DataService in the components, then subscribe to the currentMessage observable and set its value equal to the message variable.

Now if we create a function in any one of these components that changes the value of the message. The updated value is automatically broadcasted to all other components.

shared.service.ts

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable()
export class SharedService {

  private eventSource = new BehaviorSubject<string>("default message");
  eventSubject = this.eventSource.asObservable();

  constructor() { }

  emitEvent(value: string) {
    this.eventSource.next(value)
  }

}

sibling.component.ts

import { Component, OnInit } from '@angular/core';
import { DataService } from "../data.service";

@Component({
  selector: 'app-sibling1',
  template: `
     {{message}}
   `,
   styleUrls: ['./parent.component.css']
})
export class SiblingComponent1 implements OnInit {

  message: string;

  constructor(private data: DataService) { }

  ngOnInit() {
    this.data.eventSubject.subscribe(value =>  this.showValues(value));
  }
}

sibling.component.ts

import { Component, OnInit } from '@angular/core';
import { SharedService } from "../shared.service";

@Component({
  selector: 'app-sibling2',
  template: `
    {{message}}
    <button (click)="emitEvent()">New Message</button>
  `,
  styleUrls: ['./sibling2.component.css']
})
export class SiblingComponent2 implements OnInit {

  message: string;

  constructor(private service: SharedService) { }

// emit value in oninit
  ngOnInit() {
   this.service.emitEvent("Hello from Sibling-1");
  }

// emit value on event
  emitEvent() {
    this.service.emitEvent("Hello from Sibling");
  }   
}

Why use Service ?

Angular distinguishes components from services in order to increase modularity and reusability. and It's Good Practice to Delegate complex component logic to services

From Angular Style Guide
Do limit logic in a component to only that required for the view. All other logic should be delegated to services.

Do move reusable logic to services and keep components simple and focused on their intended purpose.

Why? Logic may be reused by multiple components when placed within a service and exposed via a function.

Why? Logic in a service can more easily be isolated in a unit test, while the calling logic in the component can be easily mocked.

Why? Removes dependencies and hides implementation details from the component.

Why? Keeps the component slim, trim, and focused.

Usage of Services In Angular also ensures that you are not violating DRY and SRP principles of software development,For your scenario the best solution is to use a service

Vikas
  • 11,859
  • 7
  • 45
  • 69