2017-02-16 52 views
1

我從一個視圖(稱爲bestSellersView)導航到另一個視圖(BookDetailsView)。有多個不同的「父」視圖可以導航到「書詳細信息」,並且他們都需要將要查看的書傳遞到下一個視圖。我不想將源視圖注入到細節視圖中,因爲一些線程會提示,因爲我的構造函數會隨着使用細節子視圖的每個新視圖一起增長。將數據傳遞給Aurelia中尚未加載的視圖

我正在嘗試使用事件聚合器,但是由於事物的生命週期,我總是在第一次導航時收到空白詳細信息屏幕。當我第一次導航到「書籍詳細信息」視圖時,ViewDetailsMessage尚未在發佈者(暢銷書)發送郵件之前訂閱。由於我將viewmodel設置爲singleton,隨後的點擊工作正常(因爲詳細信息視圖已經構建並訂閱了該事件)。

如何解決Aurelia的雞蛋問題?

編輯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

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」。當用戶選擇一本書時,Source將其保存在本地並導航到「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(urlParams, routeMap, navInstr) { 
    this.getPositionData(routeMap.settings.fileInfo); 
} 

但是,導航執行後,設置並未保留。

+0

看起來你只是試圖在視圖之間共享狀態。我需要在從主 - >詳細信息視圖進行導航時共享狀態存儲。我不確定你提到的關於構造函數注入的線程。我可能不完全瞭解您的場景或您參考的線索。 –

+0

基本上我見過建議人們通過使用構造函數注入來引用他們的子viewmodel中的父viewmodel。然後,孩子直接訪問父母所需的價值。如果我正確地理解了你,你註冊一個單獨的對象與IOC容器,稱爲'國家商店',你注入父母和孩子? – Bitfiddler

+0

這正是我所做的。默認情況下,所有注入的對象都是單例,所以除了正常注入外,我不必做任何事情。然後使用set/get方法來處理任何我需要的狀態。 –