オブザーバブルがなければ、HTMLテンプレートに次の行を書くことができます。
<div *ngIf="(myVarA || myVarB) && myVarC !== x"></div>
すべてのmyVar
変数が実際に観測可能になった場合、この行をどのように変換しますか?
<div *ngIf="((myVarA | async) || (myVarB | async)) && (myVarC | async) !== x">
動作しません。
別の質問では( 2つの非同期サブスクリプションを1つに入れるAngular * ngIfステートメント )2つ以上のオブザーバブルを1つのngIfに結合する可能性
<div *ngIf="{ a: myVarA | async, b: myVarB | async } as result"></div>
ただし、ngIfの評価に使用される式でブール演算子(またはそのことについては演算子)を使用する可能性はありません。
どうすればこの問題に取り組むことができますか?私のすべてのObservableはその下でBehaviorSubjectを使用していることに注意してください。基本的に私が欲しいのは、テンプレート内でcombineLatest
演算子を使用することだと思います。
ボーナス:式全体が後でテンプレートで使用するためにtrueと評価された場合(myVarA | async as varA
のように)、myVarAの単一の値を抽出する方法はありますか?
combineLatest
の使用はどうですか?
例えば:
import { combineLatest } from 'rxjs/observable/combineLatest';
import { Observable } from 'rxjs/Observable';
@Component({...})
export class FooComponent {
obs1$: Observable<bolean>;
obs2$: Observable<bolean>;
obs3$: Observable<bolean>;
constructor(){
// set observables
}
get combined$(){
return combineLatest(
this.obs1$,
this.obs2$
this.obs3$,
(one,two,three)=>(one || two) && three);
}
}
// template
<div *ngIf="combined$ | async">
ガイダンスについては、次のフィドルを確認してください。
https://jsfiddle.net/uehasmb6/11/
combineLatest
演算子の詳細 ここ
更新:しかし、それでもすべてのロジックをテンプレート内に保持したい場合は、次のようなことを試すことができます。
<div *ngIf="((myVarA | async) || (myVarB | async)) && ((myVarC | async) !== x)">
しかし、私はこれに対してあなたに忠告します。 HTMLテンプレートを可能な限りクリーンに保つことは グッドプラクティス です。
最初はpaymentSelected == false && mode == 'addPayment'
を配置するのは簡単ですが、新しい条件を追加する必要がある場合は、いくつかの場所でUIを更新する必要があります。
showPaymentPanel$
と呼ばれるオブザーバブルを公開することをお勧めします。そうすると、.ts
とテンプレートファイルの両方で、それが何のためにあるのかが明確になります:*ngIf="showPaymentPanel$ | async"
。これにより、テストも簡単になります。
しかし、私は次のような多くのコードで終わっていました:
showTokenizedPaymentMethods$ = combineLatest(this.hasTokenizedPaymentMethods$,
this.showAvailablePaymentMethods$).
pipe(map(([ hasTokenizedMethods, showAvailableMethods ]) =>
showAvailableMethods && hasTokenizedMethods));
そして、それは混乱です!複数の非同期パイプよりもさらに悪い可能性があります!
そこで、ヘルパー関数を作成して新しいオブザーバブルを生成 :(グローバルにどこか)
export const allTrue = (...observables: Array<ObservableInput<boolean>> ) => combineLatest(observables).pipe(map(values => values.every(v => v == true) ), distinctUntilChanged());
export const allFalse = (...observables: Array<ObservableInput<boolean>> ) => combineLatest(observables).pipe(map(values => values.every(v => v == false) ), distinctUntilChanged());
export const anyTrue = (...observables: Array<ObservableInput<boolean>> ) => combineLatest(observables).pipe(map(values => values.find(v => v == true) != undefined ), distinctUntilChanged());
export const anyFalse = (...observables: Array<ObservableInput<boolean>> ) => combineLatest(observables).pipe(map(values => values.find(v => v == false) != undefined), distinctUntilChanged());
注:これらはパイプで使用される演算子ではありません。
Tsファイルで、次のようにオブザーバブル(UI固有の名前)を作成します。
public showPaymentPanel$ = allTrue(this.hasTokenizedPaymentMethods$, this.showAvailableMethods$);
通常、既存のオブザーバブルが存在する場合でも、UIオブザーバブルを作成します。
public showAccountDetails$ = this.isLoggedIn$; // this condition is always subject to change
それらを作成することもできます。
public showSomethingElse$ = allTrue(this.showPaymentPanel$, this.whateverItIs$);
次のようにグループ化されたUIにそれらを公開することがあります。
public ui = { this.showPaymentPanel$, this.showSomethingElse$ );
次に使用法:
`*ngIf="ui.showPaymentPanel$ | async"`
(ui
のみを公開する必要があるため、テンプレートでは、何を許可するかが非常に明確になります)
できるだけ1本のパイプに制限してください!
Jota.Toledoの答えはまったく問題ありませんが、ngIfの後に式の一部にアクセスする方法についての私の「ボーナス」の質問をフォローアップしたいと思います。
基本的に私がしているのは、Jota.Toledoが説明したように、クラス内の2つ以上のオブザーバブルを結合することだけです。ただし、1つのオブザーバブルはブール値ではありませんが、ngIfの後に使用可能にする必要があるアイテムが含まれています。
次に、次のことを行うのは簡単です。
newObs = combineLatest(
this.itemObs,
this.boolObs1
this.boolObs3,
(item, bool1, bool2) => ((item || bool1) && bool2) ? item : null
);
ngIf内のnull以外のオブジェクトの真実性に依存できるためです。 ngIfは次のようになります
<div *ngIf="newObs | async as item"></div>
もちろん、ngIfの後に複数のアイテムが必要な場合、これは機能しません。この場合、ネストされたdivセクションで2つのngIfを使用する必要があります。