Arūnas Smaliukas
Arūnas Smaliukas

Reputation: 3321

Angular 2.x watching for variable change

I'm migrating from angular 1.x to 2.x but my brains still think in angular 1.x so sorry for silly questions.

What I need is to take some action when one of my scope variables component properties changes. I found a solution but I think there should be better solution

export class MyApp {
    router: Router;
    location: Location;
    fixed: boolean = true;

    private set isFixed(value:boolean) {
        this.fixed = value;

        //TODO: look here
        console.log('isFixed changed', value);
    }

    private get isFixed():boolean {
        return this.fixed;
    }

    constructor(router: Router, location: Location) {
        this.router = router;
        this.location = location;
    }
}

Look at the line console.log('isFixed changed', value); It's what I need and it's working. But I made it by declaring getter and setter, but isn't there a better solution to watch variables? Like in angular 1.x was $scope.$watch?

I think my component code should look like

export class MyApp {
    router: Router;
    location: Location;
    isFixed: boolean = true;

    //TODO: $watch for isFixed change {
        console.log('isFixed changed', value);
    // }

    constructor(router: Router, location: Location) {
        this.router = router;
        this.location = location;
    }
}

Upvotes: 43

Views: 111207

Answers (5)

kattoha
kattoha

Reputation: 211

I think it is possible to use simple getter and setter for this purpose.

class Example {
  private _variable: string = "Foo";
  set variable(value: string) {
    this._variable = value;
    console.log("Change detected: ", this.variable);
  }
  get variable(): string {
    return this._variable;
  }
}
let example = new Example();
console.log(example.variable);
example.variable = "Bar";
console.log(example.variable);

And output will be:

Foo
Change detected: Bar
Bar

Upvotes: 1

Darren Shewry
Darren Shewry

Reputation: 10420

You might find this answer to Delegation: EventEmitter or Observable in Angular2 helpful (worked for me).

Essentially you could use a BehaviorSubject, which allows you to set an initial value for the property you're interested in, then subscribe to changes to that property wherever that service is injected.

e.g.

export class SomeService {
  private fixed = new BehaviorSubject<boolean>(true); // true is your initial value
  fixed$ = this.fixed.asObservable();

  private set isFixed(value: boolean) {
    this.fixed.next(value);
    console.log('isFixed changed', value);
  }

  private get isFixed():boolean {
    return this.fixed.getValue()
  }

  constructor(router: Router, location: Location) {
    this.router = router;
    this.location = location;
  }
}

Then in a class (e.g. Component) that's interested in the fixed value:

export class ObservingComponent {
  isFixed: boolean;
  subscription: Subscription;

  constructor(private someService: SomeService) {}

  ngOnInit() {
    this.subscription = this.someService.fixed$
      .subscribe(fixed => this.isFixed = fixed)
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

Update value:

export class Navigation {
  constructor(private someService: SomeService) {}

  selectedNavItem(item: number) {
    this.someService.isFixed(true);
  }
}

Upvotes: 30

Manoj Rana
Manoj Rana

Reputation: 3460

To auto get updated value by this service

NOTE: I tested it in Angular 9 my service file

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

@Injectable({
    providedIn: 'root'
})
export class SharedService {
    private fixed= new BehaviorSubject<boolean>(false);
    fixed$ = this.fixed.asObservable();

    constructor() {}

    updateFixedValue(value: boolean) {
        this.fixed.next(value);
        console.log('fixed changed', value);
    }
}

Now you can get value in any component (within ngOnInit or anywhere you want) like below NOTE: this value will be change automatically after update

this.sharedService.fixed$.subscribe(val=>{ this.isFixed = val; });

and you can update or set new value from any component like below

this.sharedService.updateFixedValue(your_boolean_value);

Thanks, I hope it's work for you.

Upvotes: 2

Kody
Kody

Reputation: 975

See Angular2 Component Interaction (has code examples).

The short answer to your question is that it really just depends on what you are trying to do. Even then, there are multiple ways to do what you want to do even if it's not really intended for it. So, I think it's best if you just take a few minutes to look at their documentation about Component Interaction and Forms.

My personal preference is to use events when a property has changed. The ngOnChanges event can be used for this but I prefer to work with @Input and @Output, and form value changed events (Angular2 Forms).

Hope this helps and gives you a direction you want to take.

Upvotes: 1

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 658017

You might want to implement the OnChanges interface and implement the ngOnChanges() method. This method is called whenever one of the components input or output binding value changes. See also https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html

Dart code example

  @Input() bool fixed;

  @override
  void ngOnChanges(Map<String, SimpleChange> changes) {
    print(changes);
  }

Upvotes: 33

Related Questions