Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Update a Component without refreshing full page - Angular

My Page structure is:

<app-header></app-header>
<router-outlet></router-outlet>
<app-footer></app-footer>

How can I update/refresh the app-header component, without refreshing the whole page?

I want to hide a "Sign-In" link in the header, once the user had successfully logged in. The header is common in all the components/routes.

like image 543
Aravinthan M Avatar asked Sep 05 '17 05:09

Aravinthan M


People also ask

How do you refresh a component from another component in angular 9?

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.

How do I stop angular refresh?

You cannot prevent page refresh. The browser user can always hit F5. The "onbeforeunload" approach will allow you to warn the user, but you can't prevent it.


4 Answers

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); } 
like image 154
Faisal Avatar answered Sep 28 '22 04:09

Faisal


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 
like image 43
Jayanth Bhansali Avatar answered Sep 28 '22 03:09

Jayanth Bhansali


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');
like image 25
Carsten Avatar answered Sep 28 '22 03:09

Carsten


You just need to notify Angular to update the component with a ChangeDetectorRef. So, inside your header component:

constructor(private cd: ChangeDetectorRef) {}

loggedUserEvent(user: User): void {
  this.username = user.username; 
  this.enableDisconnectButton();

  //... Add more logic to it

  this.cd.detectChanges();
}

That should be enough

like image 37
EliuX Avatar answered Sep 28 '22 02:09

EliuX