How to Update a Component without refreshing full page - Angular
You can use a BehaviorSubject
for communicating between different components throughout the app. You can define a data sharing service containing the BehaviorSubject
to which you can subscribe and emit changes.
Define a data sharing service
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable()
export class DataSharingService {
public isUserLoggedIn: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
}
Add the DataSharingService
in your AppModule
providers entry.
Next, import the DataSharingService
in your <app-header>
and in the component where you perform the sign-in operation. In <app-header>
subscribe to the changes to isUserLoggedIn
subject:
import { DataSharingService } from './data-sharing.service';
export class AppHeaderComponent {
// Define a variable to use for showing/hiding the Login button
isUserLoggedIn: boolean;
constructor(private dataSharingService: DataSharingService) {
// Subscribe here, this will automatically update
// "isUserLoggedIn" whenever a change to the subject is made.
this.dataSharingService.isUserLoggedIn.subscribe( value => {
this.isUserLoggedIn = value;
});
}
}
In your <app-header>
html template, you need to add the *ngIf
condition e.g.:
<button *ngIf="!isUserLoggedIn">Login</button>
<button *ngIf="isUserLoggedIn">Sign Out</button>
Finally, you just need to emit the event once the user has logged in e.g:
someMethodThatPerformsUserLogin() {
// Some code
// .....
// After the user has logged in, emit the behavior subject changes.
this.dataSharingService.isUserLoggedIn.next(true);
}
To refresh the component at regular intervals I found this the best method. In the ngOnInit method setTimeOut function
ngOnInit(): void {
setTimeout(() => { this.ngOnInit() }, 1000 * 10)
}
//10 is the number of seconds
One of many solutions is to create an @Injectable()
class which holds data that you want to show in the header. Other components can also access this class and alter this data, effectively changing the header.
Another option is to set up @Input()
variables and @Output()
EventEmitters which you can use to alter the header data.
Edit Examples as you requested:
@Injectable()
export class HeaderService {
private _data;
set data(value) {
this._data = value;
}
get data() {
return this._data;
}
}
in other component:
constructor(private headerService: HeaderService) {}
// Somewhere
this.headerService.data = 'abc';
in header component:
let headerData;
constructor(private headerService: HeaderService) {
this.headerData = this.headerService.data;
}
I haven't actually tried this. If the get/set doesn't work you can change it to use a Subject();
// Simple Subject() example:
let subject = new Subject();
this.subject.subscribe(response => {
console.log(response); // Logs 'hello'
});
this.subject.next('hello');