1

私は、オブザーバブルオブジェクトのプロパティを更新する必要があります。私はそれを動作させることができたが、私はそれをどうやって行ったのか本当に好きではない。Observable/BehaviorSubjectをコードから更新するには?

next(filter$: BehaviorSubject<GridCollectionFilter>, collection: GridCollectionModel<any>) { 
    let filter = filter$.value; 

    if (!filter.page) { 
    filter.page = 1; 
    } 

    filter.page++; 

    if (filter.page > collection.pageCount) { 
    filter.page = collection.pageCount; 
    } 

    this.updateFilter(filter$); 
} 

first(filter$: BehaviorSubject<GridCollectionFilter>) { 
    filter$.value.page = 1; 
    this.updateFilter(filter$); 
} 

last(filter$: BehaviorSubject<GridCollectionFilter>, collection: GridCollectionModel<any>) { 
    filter$.value.page = collection.pageCount; 
    this.updateFilter(filter$); 
} 

updateFilter(filter$: BehaviorSubject<GridCollectionFilter>, filter?: GridCollectionFilter) { 
    filter$.next(_.clone(filter || filter$.value)); 
} 

この場合にはfilter$値オブジェクトを更新するために、よりエレガントな方法はありますか?

filter$.next(_.clone(filter$.value))というコードを使って、観測されたオブジェクトのいくつかのプロパティを単に更新するたびに、オブザーバブルのクローンを自分自身に与えるという考えは本当に嫌です。私は参照を中断するために_.clone()を使用しています(そうでなければ、rxjs distinctUntilChanged()は明白な理由のために起動しません)。

私がやっていることを短縮するrxjs拡張がありますか?私は内部でfilter$.next(_.clone(filter$.value))を行うfilter$.commitValueChanges()の行に沿って何かを考えています。

私はobservablesにはかなり新しいので、私はこれについて完全に間違った方法で最初に考えているのかどうかはわかりません。私は、変更リスナーをトリガーしたいときに、私が新しい状態をコミットするはずであることを理解しています。フィルタ$ .valueを直接変更する必要があるかどうかはわかりません。または、filter(フィルタ)とfilter$(フィルタの観測可能)の2つのオブジェクトを持つことを想定していますが、filterの変更が発生するたびにfilter.next()を提出するだけで、絶対にfilter$を突然変更することはありませんか?しかし、これでは2つのオブジェクトがあります.1つは、アプリケーションを変更していて、さまざまなイベントハンドラを取り付けることによって手動で処理しなければならないオブジェクトと、もう1つを更新できるオブジェクトです。filter$です。それは私にとっては過度でハッキリなようです。

Thnx。

答えて

1

コードから_clone()を削除するには、distinctUntilKeyChanged()を使用する必要があります。オブジェクト内のキーが変更されたかどうかをチェックします。

DistinctUntilKeyChanged API

しかし、より良いaproachは次のとおりです。

filter$: BehaviorSubject<GridCollectionFilter>; 
collection: GridCollectionModel<any>; 
currentFilter: GridCollectionFilter; 

ngOnInit() { 
    this.filter$.subscribe(filter => { 
    this.currentFilter = filter; 
    // Here for example invoke rest api with filter to change collection 
    }) 
} 

next() { 
    if (!this.currentFilter.page) { 
    this.currentFilter.page; 
    } 

    this.currentFilter.page++; 

    if (this.currentFilter.page > this.collection.pageCount) { 
    this.currentFilter.page = collection.pageCount; 
    } 

    this.filter$.next(this.currentFilter); 
} 

first() { 
    this.currentFilter.page = 1; 
    this.filter$.next(this.currentFilter); 
} 

last(filter$: BehaviorSubject<GridCollectionFilter>, collection: GridCollectionModel<any>) { 
    this.currentFilter.page = collection.pageCount; 
    this.filter$.next(this.currentFilter); 
} 
+1

私は 'distinctUntilKeyChanged()'ビットが好きです。これはとても役に立ちます。私はそれを認識していませんでした。しかし、追加の複雑さを加えてコードを重複させてしまうので、追加のcurrentFilterフィールドを追加することは私にはあまりありません。私は2つのフィルタオブジェクトを持つことを避けようとしており、1つのトリックを行うことができるはずの意見です。彼らのうちの2人がハッキーと乱雑に感じる。 – pootzko

+0

貼り付けられたメソッドは実際にはコンポーネントではなくサービスクラスにあります。 'filter $' observableはカスタム 'BaseGridComponent'で作成されたもので、次にイベントハンドラメソッド(次に貼り付けられなかった最後のものや他のもの)は' filter $ 'を更新するはずです理にかなっている。 'filter $ .value'は監視されるもので、変更されると、フィルタオブジェクトはバックエンドに送られてデータを取得します。 – pootzko

+0

それをコンポーネントBaseGridComponentに移動します。 BaseGridComponentによって拡張されたグリッドでは、フィルタの変更を待機し、残りのコレクションをリロードするための残りのAPIを呼び出します。あなたが思うこと ? – pioro90

0

あなたの唯一の問題はあなたが多分これらのヒントの一つがお手伝いしますオブジェクトのクローンを作成する必要があるということである場合:

  • distinctUntilChanged演算子は、デフォルトでオブジェクトIDを比較します。ただし、任意の比較ログインを実装するために使用できるオプションのcompareが必要です。

    Object.assign({}, filter) 
    
    :あなたはこれらのいずれかを使用することができますだけで浅いコピーを作成して[O​​K]をしている場合にも、同じ性質

    .distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)) 
    
  • で2つの異なるインスタンスを比較するために使用することができ

    .distinctUntilChanged((a, b) => a.page === b.page) 
    

    または

    { ...filter } 
    

    これらはどちらも浅いコピーを作成します。

    JSON.parse(JSON.stringify(filter)) 
    

    この方法を使用すると、任意のサードパーティは必要ありません:あなたは深いコピーを必要としますが、パフォーマンスを心配していない場合は

  • あなたはJSONを使用することができます(あなたは非常に小さなオブジェクトを持っているように思えます)としょうかん。

+1

それは実際にはクローンだけではありません。私は '_.clone()'(および一般的にlodash)を持っていても大丈夫ですので、私はすべてのアプリケーションでデフォルトでそれを持っているので気にしません。 '.next()'をそれ自身の複製された観測可能な値で与えるのは、プロパティを2つ更新するなどの簡単な処理のオーバーヘッドです。私は '.nextSelf()'と呼ばれる単純なメソッドを使うとコードの量を減らすことができます。しかし、私はその判断を下す前に観測値をもう少し調べる必要があります。今はちょっと単純化する方法を探しています。 – pootzko

+0

私はあなたのコードが何をすべきか理解していないと思います。 – martin

+1

私は本当に私の質問の周りにあまりにも多くのノイズがあると思ったので、私は全部をみんなを退屈したくありませんでした。 'filter $ .next(_ .clone(filter $ .values))'の必要性を置き換える何らかの 'filter $ .commitValueChanges()'があるかどうか疑問に思っています。私は少し質問を更新します。いずれにせよ、答えを書くことに感謝します。 – pootzko

0

私はまったく同じ問題を抱えているため、あなたの問題を完全に理解しています。私は、被験者の価値を直接変更していたため、さまざまな角度変化の問題に直面しました。今私はちょうど_.cloneDeepの値を変更してから、それを.next()で主語に戻します。私も、件名が変更を検出して新しいオブジェクトを公開するためのある種のショートカットに感謝します。当分の間、私はより良い解決策を見つけられませんでした。

関連する問題