Reputation: 1096
I have this piece of code:
app.component.ts:
import {Component, AfterViewInit, ChangeDetectorRef} from '@angular/core';
import {Subject} from 'rxjs/Subject';
import 'rxjs/add/operator/scan';
import 'rxjs/add/operator/filter';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
changes$ = new Subject<number>();
current$ = this.changes$
.scan((x, y) => x + y, 0)
.filter((x) => x >= 0);
constructor(private cdRef: ChangeDetectorRef) {}
ngAfterViewInit(): void {
this.changes$.next(0);
this.cdRef.detectChanges();
}
}
app.component.html:
<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center">
<button (click)="changes$.next(-1)">-1</button>
<button (click)="changes$.next(1)">+1</button>
<div>
<span>{{ current$ | async }}</span>
</div>
<div>
<span>{{ current$ | async }}</span>
</div>
<div>
<span>{{ current$ | async }}</span>
</div>
</div>
My problem was that I didn't want to go below 0 so I added the filter operator. This solved my problem but when I get to 0 and press like 10 times the minus button and then press the add button again, it doesn't get updated unless I press the add button a lot of times.
Why is this? How can I solve that?
Example:
Upvotes: 2
Views: 534
Reputation: 1901
Try this in the scan. The reason is that every time a value is emitted the scan will be processed no matter whether it is filtered or not.
.scan((x, y) => (x + y) >= 0 ? x + y : 0, 0)
Upvotes: 3
Reputation: 4794
Well, first of all - as Deepak said you need to move it to the scan()
. The reason being is that when changes$
subject emits new value scan()
will still continue to count whatever it emits including negative numbers, but you just won't see it from behind the filter()
. You need precisely to stop counting if you don't want your counter to go below 0, not masking its output by filter()
.
Also, you don't need to manually emit the first value, you don't need constructor and ngAfterViewInit calling ChangeDetectorRef. This all is totally unnecessary.
Below is the fixed code:
import {Component} from '@angular/core';
import {Subject} from 'rxjs/Subject';
import 'rxjs/add/operator/scan';
import 'rxjs/add/operator/startWith';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
changes$ = new Subject<number>();
current$ = this.changes$
.startWith(0)
.scan((x, y) => (x + y) >= 0 ? x + y : 0, 0);
}
Upvotes: 1