Christopher
Christopher

Reputation: 1772

Define a custom Observable in Angular2+

I have a simple css animation library that allows the display of an animation by calling loadService.animate(boolean); but sadly it does not function anymore as I have been wrongly using an EventEmitter in my service like such:

@Injectable()
export class LoadService {
    @Output() animating: EventEmitter<any> = new EventEmitter();

    constructor() {}

    // User calls animate, we emit an event with the new boolean value
    public animate(val: boolean) {
        this.animating.emit(val);
    }

    getValue(): any {
        return this.animating;
    }
}

And subscribing to it in my component:

// Animation shown when animate == true
animate: boolean;

ngOnInit(): void {
    this.loadService.getValue().subscribe((status: boolean) => {
        // Events caught, we change the boolean to display the animation
        this.animate = status;
    });
    this.handleShape();
}

But my subscription never catches anything, so I figured I wanted to create a custom Observable in order to simply catch when a user calls animate and consequently change the value of my boolean.

How may I define a custom observable in Angular2+? And how may I implement it in this scenario?

Upvotes: 1

Views: 1947

Answers (2)

Hamid Asghari
Hamid Asghari

Reputation: 5889

LoadService

In our service we create a BehaviorSubject with default value of false:

private _animate = BehaviorSubject(false);
get animate(): Observable<any>{
    return this._animate.asObservable();
}

Also, in LoadService, to update our observable value:

toggleAnimation(value: boolean){
   oldValue = this._animate.getValue();
   this._animate.next(!oldValue);
}

Component

Now in our component, you can subscribe to it like this:

constructor(private service: LoadService) {
    this.service.animate.subscribe(state => {
        // do stuff
        console.log(state);
    })
};

Upvotes: 4

LookForAngular
LookForAngular

Reputation: 1070

Angular team discourage the usage of eventemitter in a service, since it's used as an abstraction around a Subject. You can create an observable with custom logic by using the new keywork, and by providing the logic of the emission, or you can use a Subject, which is an observable and an observer, think of it as the most similar implementation of the observer pattern.

loadServiceSubject : Subject<any> = new Subject();
loadService$ : Observable<any> = loadServiceSubject.asObservable();
// other code

Think of the subject as a proxy between the event emitter and the listeners, anytime you call the next function on the subject, the emitted value will be pushed to all the subscribers of the observable.

// in client code
// suppose the service is injected in the constructor
this.animationService.loadService$.subscribe( this.doStuffOnNextCallback );

The "event" emitter just need to call the next, error or complete function on the subject itself.

// producer code, supposing it's also injected
this.animationService.loadServiceSubject.next(true);

Upvotes: 0

Related Questions