Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 - subscribe to Service variable changes

Tags:

I have an authentication service that makes the authenticated variable equal to true or false.

checkAuthentication(){
  this._authService.getAuthentication()
    .subscribe(value => this.authenticated = value);
}

How do I execute a function when this.authenticated has changed value? ngOnChanges is not picking up the change.

like image 974
ClickThisNick Avatar asked Feb 21 '16 18:02

ClickThisNick


People also ask

Which of the following detects the changes during run time in an Angular application?

Angular provides two strategies for Change Detection. In its default strategy, whenever any data is mutated or changed, Angular will run the change detector to update the DOM. In the onPush strategy, Angular will only run the change detector when a new reference is passed to @Input() data.

What triggers change detection Angular?

By default, angular will run the change detector every time @Input() data is changed or modified. But with OnPush strategy, the change detector is only triggered if the data passed on @Input() has a new reference.

How does angular detect changes in service?

To run the change detector manually: Inject ChangeDetectorRef service in the component. Use markForCheck in the subscription method to instruct Angular to check the component the next time change detectors run. On the ngOnDestroy() life cycle hook, unsubscribe from the observable.

What is change detection and How it is handled?

Change detection is the strategy by which Angular decides what actions to be performed when the state of the app or component is changed. The changes to the state of the components can be triggered by user interactions like clicking a button, changing input values, or by HTTP requests, etc.


2 Answers

To keep authenticated in service and share it between components you can use BehaviorSubject, it's value to check authentication in different places, and it's subscribe() method to react on change...

class AuthService {
  public authenticated = new BehaviorSubject(null);
  getAuthentication() {
    this._http.get('/authenticate')
      .map(response => response.json())
      .map(json => Boolean(json)) // or whatever check you need...
      .subscribe((value: boolean) => this.authenticated.next(value))
  }
}

class Component {
  constuctor(private _authService: AuthService) {
    // Only check once even if component is 
    // destroyed and constructed again
    if (this._authService.authenticated.value === null)
      this._authService.getAuthentication();
  }

  onSubmit(){
    if (!this._authService.authenticated.value)
      throw new Error("You are authenticated!")
  }
}

How do I execute a function when this.authenticated has changed value?

  this._authService.authenticated
   .subscribe((value: boolean) => console.log(value))
like image 127
Sasxa Avatar answered Sep 21 '22 12:09

Sasxa


I think that you could leverage the get / set syntax of TypeScript to detect when your authenticated property of your service is updated:

  private _authenticated:Boolean = false;
  get authenticated():Boolean {
        return this._authenticated ;
  }
  set authenticated ( authenticated Boolean) {
    // Plugin some processing here
      this._ authenticated = authenticated;
  }

When assigning a value, the "set authenticated" block is called. For example with such code:

this.authenticated = true;

See this question for more details:

  • get and set in TypeScript

That said you could also leverage an EventEmitter property in the service. When the authenticated property is updated, the corresponding event could be fired.

export class AuthService {
  authenticatedChange: Subject<boolean> = new Subject();

  constructor() {}

  emit(authenticated) {
    this.authenticatedChange.next(authenticated);
  }

  subscribe(component, callback) {
    // set 'this' to component when callback is called
    return this.authenticatedChange.subscribe(data => {
      callback(component, data);
    });
  }
}

See this link for more details:

  • Delegation: EventEmitter or Observable in Angular2
like image 42
Thierry Templier Avatar answered Sep 17 '22 12:09

Thierry Templier