2017-02-16 4 views
1

私は1つのビュー(bestSellersViewと呼ぶ)から別のビュー(BookDetailsView)へナビゲートしています。 「ブックの詳細」にナビゲートできる複数の異なる「親」ビューがあり、それらはすべて、表示されるブックを次のビューに渡す必要があります。詳細ビューを使用する新しいビューごとにコンストラクタが大きくなるので、いくつかのスレッドが示唆するように、ソースビューを詳細ビューに挿入したくありません。Aureliaの未ロードビューへのデータの受け渡し

私はイベントアグリゲータを使用しようとしていますが、物事のライフサイクルのために、私は最初にナビゲートするときに常に空の詳細画面を表示しています。最初に「ブックの詳細」ビューに移動すると、パブリッシャー(ベストセラー)がメッセージを送信する前にViewDetailsMessageがまだ購読されていません。 viewmodelをシングルトンに設定しているので、詳細ビューは既に構築されており、イベントに登録されているので、後続のクリックは正常に機能します。

アウレリアでこの鶏卵の問題を回避するにはどうすればよいですか?

編集ここ01

が、私は問題を抱えたとき、私が何をしていたかである:

Master.ts:

import { JsonServiceClient } from "servicestack-client"; 
import { 
    ListPendingHoldingsFiles, 
    ListPendingHoldingsFilesResponse, 
    SendHoldings, 
    PositionFileInfo 
} from "../holdingsManager.dtos"; 
import { inject, singleton } from "aurelia-framework"; 
import { Router } from "aurelia-router"; 
import { EventAggregator } from "aurelia-event-aggregator"; 
import { GetPendingPositionMessage } from "../common/GetPendingPositionMessage"; 

@singleton() 
@inject(Router, EventAggregator) 
export class Pending { 
    router: Router; 
    positions: PositionFileInfo[]; 
    client: JsonServiceClient; 
    eventAgg: EventAggregator; 

    constructor(router, eventAggregator) { 
     this.router = router; 
     this.eventAgg = eventAggregator; 
     this.client = new JsonServiceClient('/'); 
     var req = new ListPendingHoldingsFiles(); 
     this.client.get(req).then((getHoldingsResponse) => { 
      this.positions = getHoldingsResponse.PositionFiles; 
     }).catch(e => { 
      console.log(e); // "oh, no!" 
     }); 
    } 

    openHoldings(positionInfo) { 
     this.eventAgg.publish(new GetPendingPositionMessage(positionInfo)); 
     this.router.navigate('#/holdings'); 
    } 
} 

Child.ts:

import { JsonServiceClient } from "servicestack-client"; 
import { inject, singleton } from "aurelia-framework"; 
import { Router } from 'aurelia-router'; 
import { EventAggregator } from "aurelia-event-aggregator"; 
import { GetPendingPositionMessage } from "../common/GetPendingPositionMessage"; 
import { 
    GetPendingHoldingsFile, 
    GetPendingHoldingsFileResponse, 
    Position, 
    PositionFileInfo 
} from "../holdingsManager.dtos"; 

@singleton() 
@inject(Router, EventAggregator) 
export class Holdings { 
    router: Router; 
    pendingPositionFileInfo: PositionFileInfo; 
    position: Position; 
    client: JsonServiceClient; 
    eventAgg: EventAggregator; 

    constructor(router, eventAggregator) { 
     this.router = router; 
     this.eventAgg = eventAggregator; 
     this.eventAgg.subscribe(GetPendingPositionMessage, 
      message => { 
       this.pendingPositionFileInfo = message.fileInfo; 
      }); 
    } 

    activate(params, routeData) { 
     this.client = new JsonServiceClient('/'); 
     var req = new GetPendingHoldingsFile(); 
     req.PositionToRetrieve = this.pendingPositionFileInfo; 
     this.client.get(req).then((getHoldingsResponse) => { 
      this.position = getHoldingsResponse.PendingPosition; 
     }).catch(e => { 
      console.log(e); // "oh, no!" 
     }); 
    } 
} 

ここに私が今やっていることがあります:

master.ts私は右の両親の保有ファイルを頼むことを確認するために、子供のActivateメソッドにロジックのビットを追加する必要が

import { JsonServiceClient } from "servicestack-client"; 
import { 
    ListPendingHoldingsFiles, 
    ListPendingHoldingsFilesResponse, 
    PositionFileInfo 
} from "../holdingsManager.dtos"; 
import { inject, singleton } from "aurelia-framework"; 
import { Router } from "aurelia-router"; 
import { EventAggregator } from "aurelia-event-aggregator"; 
import { GetPendingPositionMessage } from "../common/GetPendingPositionMessage"; 
import { SetPendingPositionMessage } from "../common/SetPendingPositionMessage"; 

@singleton() 
@inject(Router, EventAggregator) 
export class Pending { 
    router: Router; 
    eventAgg: EventAggregator; 
    positions: PositionFileInfo[]; 
    client: JsonServiceClient; 
    fileInfo: PositionFileInfo; 

    constructor(router, eventAggregator) { 
     this.router = router; 
     this.eventAgg = eventAggregator; 
     this.eventAgg.subscribe(GetPendingPositionMessage,() => { 
      this.eventAgg.publish(new SetPendingPositionMessage(this.fileInfo)); 
     }); 
    } 

    activate(params, routeData) { 
     this.client = new JsonServiceClient('/'); 
     var req = new ListPendingHoldingsFiles(); 
     this.client.post(req).then((getHoldingsResponse) => { 
      this.positions = getHoldingsResponse.PositionFiles; 
     }).catch(e => { 
      console.log(e); // "oh, no!" 
     }); 
    } 

    openHoldings(positionInfo) { 
     this.fileInfo = positionInfo; 
     this.router.navigate('#/holdings'); 
    } 
} 

child.ts

import { JsonServiceClient } from "servicestack-client"; 
import { inject, singleton } from "aurelia-framework"; 
import { Router } from 'aurelia-router'; 
import { 
    GetPendingHoldingsFile, 
    GetPendingHoldingsFileResponse, 
    Position, 
    SendHoldings, 
    PositionFileInfo 
} from "../holdingsManager.dtos"; 
import { EventAggregator } from "aurelia-event-aggregator"; 
import { GetPendingPositionMessage } from "../common/GetPendingPositionMessage"; 
import { SetPendingPositionMessage } from "../common/SetPendingPositionMessage"; 
import { GetDeliveredPositionMessage } from "../common/GetDeliveredPositionMessage"; 
import { SetDeliveredPositionMessage } from "../common/SetDeliveredPositionMessage"; 

@singleton() 
@inject(Router, EventAggregator) 
export class Holdings { 
    router: Router; 
    pendingPositionFileInfo: PositionFileInfo; 
    position: Position; 
    client: JsonServiceClient; 
    eventAgg: EventAggregator; 

    constructor(router, eventAggregator) { 
     this.router = router; 
     this.eventAgg = eventAggregator; 
     this.eventAgg.subscribe(SetPendingPositionMessage, message => this.getPositionData(message.fileInfo)); 
     this.eventAgg.subscribe(SetDeliveredPositionMessage, message => this.getPositionData(message.fileInfo)); 
    } 

    getPositionData(fileInfo) { 
     this.position = null; 
     this.client = new JsonServiceClient('/'); 
     var req = new GetPendingHoldingsFile(); 
     req.PositionToRetrieve = fileInfo; 
     this.client.post(req).then((getHoldingsResponse) => { 
      this.position = getHoldingsResponse.PendingPosition; 
     }).catch(e => { 
      console.log(e); // "oh, no!" 
     }); 
    } 

    activate(params) { 
     this.eventAgg.publish(new GetPendingPositionMessage()); 
     this.eventAgg.publish(new GetDeliveredPositionMessage()); 
    } 

    sendHoldings() { 
     var req = new SendHoldings(); 
     this.client.get(req).then((sendHoldingsRepsonse) => { 
      console.log("SUCCESS!"); // "oh, no!" 
     }).catch(e => { 
      console.log(e); // "oh, no!" 
     }); 
    } 
} 

。次のように

+0

私たちがどのように役立つかを確認するために、どのように行動しているかを確認するには、いくつかのコードを参照する必要があります。 –

+0

@KellyEthridge私は比較のためにいくつかのコードを追加しました。 – Bitfiddler

答えて

1

ビュー間で状態を共有する必要があるようです。私はStateStoreクラスを使用して、状態を共有したい任意のビューに注入します。デフォルトでは、注入されるすべてのオブジェクトはシングルトンであり、状態を共有しやすくなっています。非常に単純な例は、(活字体で)とすることができる:

statestore.ts

export class StateStore { 
    state: any; 
} 

masterview.ts

autoinject() 
export class MasterView { 
    constructor(private store: StateStore){ 
    } 

    doSomething(): void { 
     this.store.state = "some value"; 
     // navigate to detail view 
    } 
} 

detailview.ts

autoinject() 
export class DetailView { 
    sharedValue: any; 

    constructor(store: StateStore) { 
     this.sharedValue = store.state; 
    } 
} 

これは単を共有しますビューの間のStateStoreのインスタンスは、状態を容易に共有できるようにします。

1

私の現在のソリューションは、私はそれがしたいほどきれいではありませんけれどもすることです:

ソースビュー(bestSellersView)はシングルトンであり、「GetCurrentBookMes​​sage」に加入しています。ユーザーがブックを選択すると、ソースはそのブックをローカルに保存し、 "BookDetailsView"にナビゲートします。 BookDetailsViewが構築され、 "SetCurrentBookMes​​sage"にサブスクライブし、アクティブ化されると、GetCurrentBookMes​​sageを送信します。ソースビューは、 "SetCurrentBookMes​​sage"で応答します。

これは複数のソースで乱雑になり、正しいソースを選択するためのナビゲーションがどこから来たのかを解決する方法が必要ですが、今日ではこれが機能します。

編集01 私はまた、すべてのイベントアグリゲータのものを取り除くと、マスターのOpenHoldings方法でこれを入れて取得しようとしている。その後、

let routeConfig = this.router.routes.find(x => x.name === 'holdings'); 
    this.fileInfo = positionInfo; 
    routeConfig.settings = { 
     fileInfo: positionInfo 
    }; 
    this.router.navigateToRoute('holdings'); 

と子のActivateメソッドでこれを置く:

activate(urlParams, routeMap, navInstr) { 
    this.getPositionData(routeMap.settings.fileInfo); 
} 

ただし、ナビゲーションの実行後も設定が維持されませんでした。

+0

あなたはビュー間で状態を共有しようとしているようです。マスター→詳細ビューからナビゲートしながら共有する必要があるときは、状態ストアを挿入します。コンストラクタインジェクションについてどのスレッドが参照しているのかよく分かりません。私はあなたのシナリオやあなたが参照しているスレッドのことを十分に理解していないかもしれません。 –

+0

私は基本的に、コンストラクタインジェクションを使用して、子ビューモデルで親ビューモデルを参照するように提案しました。次に、子は親から必要な値に直接アクセスします。私があなたを正しく理解している場合、あなたは親と子の両方に注入する 'state-store'というIOCコンテナに別のオブジェクトを登録していますか? – Bitfiddler

+0

それはまさに私がしていることです。デフォルトでは、注入されるすべてのオブジェクトはシングルトンなので、通常の注入以外は何もする必要はありません。そして、必要な状態を処理するためにset/getメソッドを使用してください。 –

関連する問題