异步管道不绑定到Angular中的Observable

时间:2017-06-17 12:50:42

标签: angular rxjs rxjs5

我在Angular(4)中有一种情况,其中async-pipe不绑定到ngAfterViewInit()中的Observable集,除非我使用Observable.interval(1000)在构造函数中初始化它。如果删除.interval - 部分,则异步管道在ngAfterViewInit()运行时不会订阅observable。

我想在类的顶部初始化像这样的observable,但这会破坏功能:

resultStream: Observable<string>;
genderStream: Observable<number>;

我必须这样声明:

// Weird fix: I need to add .interval(?) for async pipe to work later on...
resultStream: Observable<string> = Observable.interval(1000).map(() => "");
genderStream: Observable<number> = Observable.interval(1000);

所以我的解决方案现在感觉有些不尽如人意,因为我必须使用.interval()设置。

问题在这个问题中重现:https://plnkr.co/edit/q3TR5iszU1swFrTjajEa

单击性别,然后在输入字段中输入一个整数以显示结果。

您能为我提供简单/优雅的解决方案吗? 谢谢。

完整的课程是:

import { Component, OnInit, ViewChild, ElementRef, AfterViewInit, ChangeDetectionStrategy } from '@angular/core';
import { Observable } from 'rxjs/Rx';


@Component({
    selector: 'my-app',
    template: `
    <div class="row">
    <div class="col-md-6">
        <form class="form-inline">
            <input #distance class="form-control" placeholder="Distance">
            <button #femaleGender type="button" class="btn btn-default" [class.active]="(genderStream | async) === 1">Female</button>
            <button #maleGender type="button" class="btn btn-default" [class.active]="(genderStream | async) === 0">Male</button>
        </form>
    </div>
    <div class="col-md-6">
        <h4>Result: {{ resultStream | async }}</h4>
    </div>
    </div>
`,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent implements AfterViewInit {

    // Weird fix: I need to add .interval(?) for async pipe to work later on...
    resultStream: Observable<string> = Observable.interval(1000).map(() => "");
    genderStream: Observable<number> = Observable.interval(1000);

    @ViewChild('distance') distance: ElementRef;
    @ViewChild('maleGender') maleGender: ElementRef;
    @ViewChild('femaleGender') femaleGender: ElementRef;


    ngAfterViewInit() {
        let distance$ = Observable.fromEvent(this.distance.nativeElement, 'keyup')
            .map((event: Event) => event.target)
            .map((element: HTMLInputElement) => element.value)
            .map(value => parseInt(value))
            .filter(value => !isNaN(value));

        // In the calculation 0 is used for males and 1 for females.
        let male$ = Observable.fromEvent(this.maleGender.nativeElement, 'click').map(() => 0);
        let female$ = Observable.fromEvent(this.femaleGender.nativeElement, 'click').map(() => 1);
        let gender$ = Observable.merge(male$, female$);

        this.genderStream = gender$;

        this.resultStream = Observable.combineLatest(
            distance$,
            gender$,
            (distance, gender) => calculateResult(distance, gender).toFixed(1)
        );
    }
}

const calculateResult = (distance: number, gender: number) => 18.38 + (0.033 * distance) - (5.92 * gender);

1 个答案:

答案 0 :(得分:1)

我明白了。

这是因为父组件的更改检测设置为ChangeDetectionStrategy.OnPush。在组件中禁用它和父页面就可以了。

import { Component, ChangeDetectionStrategy } from '@angular/core'

@Component({
    selector: 'parent-page',
    // Disabling OnPush change detection did the trick:
    // changeDetection: ChangeDetectionStrategy.OnPush,
    templateUrl: './parent.html'
})
export class ParentPage {}