I am currently learning angular and developing a small application a long the way. My application contains multiple components, some of which allowing the use to perform some crud operations. However, I am facing a problem that I have not been able to solve for days now.
The app classify the data in different categories which the user can update. But when the user update the data in one component and then navigates to another. The component the user navigates to does not know of the update and thus does not refresh. I know I could use window.location.reload() to reload the entire app, but I think reloading the application on each update defeats the purpose of building a SPA in the first place.
Is there a way to refresh a component after updating data on another?
To refresh, or better to say update another component from a different component, we can use the concept of Observables and Subject (which is a kind of Observable). This concept has an added benefit when data are to be received from APIs for CRUD operations.
Subject allows values to be multicasted to Observers
, which are registered to listen to the Subject. Subject is like an EventEmitter
, in simple terms, if you want to trigger an update, you can emit the new values and it can be sent to all components that you want to update. Technically, we do this by feeding the new value in Subject, by just calling next(newValue)
, and then it can be sent to all Observers
who then need to subscribe
it.
Taking an example where a message - a string is sent/updated by one component and the other component needs to listen to it and receive/update the same.
We use a common service to communicate between these components.
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class CommonService {
private subjectName = new Subject<any>(); //need to create a subject
sendUpdate(message: string) { //the component that wants to update something, calls this fn
this.subjectName.next({ text: message }); //next() will feed the value in Subject
}
getUpdate(): Observable<any> { //the receiver component calls this function
return this.subjectName.asObservable(); //it returns as an observable to which the receiver funtion will subscribe
}
}
Now below is a component that wants to update some values/wants to send the message.
import { Component } from '@angular/core';
import { CommonService } from 'provide proper path';
@Component({ templateUrl: 'sender.component.html' })
export class SenderComponent {
constructor(private Service: CommonService) { } //mention the service in constructor
sendMessage(): void {
// send message to subscribers via observable subject
this.Service.sendUpdate('Message from Sender Component to Receiver Component!');
}
}
Now below is a receiver component that wants to listen to the update
import { Component, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
import { CommonService } from 'provide proper path';
@Component({
templateUrl: 'receiver.component.html'
})
export class ReceiverComponent implements OnDestroy {
messageReceived: any;
private subscriptionName: Subscription; //important to create a subscription
constructor(private Service: CommonService) {
// subscribe to sender component messages
this.subscriptionName= this.Service.getUpdate().subscribe
(message => { //message contains the data sent from service
this.messageReceived = message;
});
}
ngOnDestroy() { // It's a good practice to unsubscribe to ensure no memory leaks
this.subscriptionName.unsubscribe();
}
}
If you want to read more on Subjects, you may see following links:
firebaseapp.com/guide/subject
https://jasonwatmore.com/post
rxjs-understanding-subjects
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With