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.

7
  • You should not call the second component from one method. You should rely on Angular to do this for you. If you could explain the relation between these two component then i guess we can accomplish it more Angular way. Commented Sep 24, 2020 at 4:43
  • stackoverflow.com/questions/49387889/… Commented Sep 24, 2020 at 4:46
  • angular.io/guide/component-interaction Commented Sep 24, 2020 at 4:47
  • @PrinceIsNinja they are sibling components not parent or child Commented Sep 24, 2020 at 4:47
  • @Vikas, thanks for the suggestion I'lltry from the link you've suggested Commented Sep 24, 2020 at 4:48

1 Answer 1

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

Sign up to request clarification or add additional context in comments.

3 Comments

should I do this.eventSubject.next(value) or this.eventSource.next(value) ??
thanks for this explanation, it is working perfectly...
@shreyshah I updated the answer use this.eventSource.next(value)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.