简体   繁体   中英

How to evaluate a condition in app.component from service in angular 7?

I have a problem with my app.component.html, i'm using this block:

<router-outlet *ngIf="!accessGranted"></router-outlet>
<div *ngIf="accessGranted" class="wrapper">
    <app-header></app-header>
    <app-left-menu></app-left-menu>

    <router-outlet></router-outlet>

    <app-footer></app-footer>
    <app-right-menu></app-right-menu>
</div>

When the accessGranted is false i load the login theme, when accessGranted its true i load everything from the dashboard. Ok this is perfect, works i expected. But the problem is... how to update the variable accessGranted from a service? currently i have this in app.component.ts:

app.component.ts

import { Component, OnInit, OnDestroy } from '@angular/core';
import { ThemeService } from './services/theme.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnDestroy {
  title = 'SmartliveWeb';

  accessGranted: boolean;

  constructor (private _themeService: ThemeService) {
    this.accessGranted = _themeService.accessGranted;
  }
}

theme.service.ts

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

@Injectable({
  providedIn: 'root'
})
export class ThemeService {

  accessGranted = false;

  constructor() {
  }
}

When user login in the app i want to change accessGranted to true to change the theme, but always stay in false. Any way to apply the changes in app.component when the accessGranted in service changes?

To update the value in the component you need to create an Observable of that variable, so when changes the variable fire the value and the component can listen it. For example:

  private static accessGranted = new Subject();
  accessGranted$ = ThemeService.accessGranted.asObservable();


onLogin(){
   if(loginSuccess){
      ThemeService.accessGranted.next(true);
   }else{
      ThemeService.accessGranted.next(false);
   }
}

And in the app.component you can subscribe as follow:

ngOnInit(){
   this._themeService.accessGranted$
          .subscribe((res) => this.accessGranted = res)
}

But I think this isn't the right way to do this. You can use as children route and use the route guards provided from angular like canActivate. Have more information here: CanActivate Doc

You could write a method to service and make accessGranted an Observable or even better: a BehaviorSubject .

In service:

export class ThemeService {

  private accessGrantedSubject$: BehaviorSubject<boolean> = new BehaviorSubject(false);

  accessGranted = () => this.accessGrantedSubject$.asObservable();

  constructor() {
  }

  setAccessGranted = (isGranted: boolean): void => {
   this.accessGrantedSubject$.next(isGranted);
  }
}

In component:

export class AppComponent implements OnInit, OnDestroy {
  title = 'SmartliveWeb';

  accessGranted: Observable<boolean>;

  constructor (private _themeService: ThemeService) {
    this.accessGranted = this._themeService.accessGranted();
  }
}

And in template, you can use async pipe:

<div *ngIf="accessGranted | async" class="wrapper">
...
</div>

If you want to change the accessGranted property, you could call the setAccessGranted() method of the service.

Hope that helps.

your assignment in constructor is wrong

constructor (private _themeService: ThemeService) {
   this.accessGranted = _themeService.accessGranted;
}

constructor (private themeService: ThemeService) {
   this.themeService = themeService;
}

login()
{
   this.themeService.login((res) => {
       this.themeService = res;
   });
}

in your theme service implement login and return true on success

this can be achieved by using shared service. This is how the code will look like:

Create a new file Service.ts

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

@Injectable()
export class SharedService {
    // Subject (emitter) for User Name Change
    AccessGrantChange: Subject<boolean> = new Subject<boolean>();

    // SetUserChange() - This method sets the local variable and emits the change
    SetAccessGrant(param: boolean) {
        this.AccessGrantChange.next(param);
    }
}

In your login component once you get the result from service, ie in subscribe method write the following code:

this._sharedService.SetAccessGrant(newCityName);

Make sure that in the constructor you have injected the service class. And in app.component.ts file in ngOnInit subscribe to the event and change the value:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { ThemeService } from './services/theme.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnDestroy {
  title = 'SmartliveWeb';

  accessGranted: boolean;

  constructor (private _themeService: ThemeService) {
    _themeService.accessGranted = this.accessGranted;
  }

  ngOnInit(){
    this._sharedService.AccessGrantChange
        .subscribe((value) => {
            this..accessGranted=value;
    });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM