2014-11-05 44 views
1

雖然想要自定義Google DataVisualization,但我想參數化控件的構造函數,但由於某種原因,當我將inputDataTable作爲參數傳遞時,它似乎不起作用。Websharper/Web.Control構造函數問題

這裏是我使用默認的數據:

module Example = 
    let headers = [|"Country"; "Population (mil)"; "Area (km2)" |] 
    let inputDataTable = [| 
    [|box "CN"; box 1234000; box 9640821|] 
    [|box "IN"; box 1133000; box 3287263|] 
    [|box "US"; box 304000; box 9629091|] 
    [|box "ID"; box 232000; box 1904569|] 
    [|box "BR"; box 187000; box 8514877|] 
    |] 

的代碼來生成網頁上的圖表。

let GeoChart headers inputDataTable = 
    Div [] 
    |>! OnAfterRender (fun container -> 
      let dataFormatter = DefaultOptions.NumberFormatter "" 
      let options = DefaultOptions.GeoChart 
      let visualization = new GeoChart(container.Dom) 
      let data = Data.GeoMapData headers inputDataTable 
      dataFormatter.format(data, 1) 
      visualization.draw(data, options) 
     ) 

「預期」控件。

type GoogleGeoChartViewer(headers, inputDataTable) = 
    inherit Web.Control() 

    [<JavaScript>] 
    override this.Body = 
    Google.Charts.GeoChart headers inputDataTable :> _ 

並使用基本模板進行測試。

let HomePage = 
    let headers = Google.Example.headers 
    let inputDataTable = Google.Example.inputDataTable 
    Skin.WithTemplate "HomePage" <| fun ctx -> 
     [ 
      Div [Text "HOME"] 
      Div [new Controls.EntryPoint()] 
      Div [new Controls.GoogleGeoChartViewer(headers, inputDataTable)] 
      Links ctx 
     ] 

但是,當我使用此代碼時:地圖不會顯示。

但是,如果我從參數列表中刪除inputDataTable和使用:

let GeoChart headers = 
    Div [] 
    |>! OnAfterRender (fun container -> 
      let dataFormatter = DefaultOptions.NumberFormatter "" 
      let options = DefaultOptions.GeoChart 
      let visualization = new GeoChart(container.Dom) 
      let inputDataTable = Example.inputDataTable 
      let data = Data.GeoMapData headers inputDataTable 
      dataFormatter.format(data, 1) 
      visualization.draw(data, options) 
     ) 

它的工作原理...

headers數組不但是造成任何問題。

會有人知道發生了什麼嗎?

謝謝你的見解。

回答

1

會發生什麼情況是,傳遞給Web.Control的構造函數的值是在服務器端構建頁面期間被序列化爲JSON的服務器端值。但是,obj類型沒有串行器,所以inputDataTableobj[][]類型)的序列化失敗。相反,在工作的版本中,inputDataTable在客戶端上構建,因此不需要序列化。

如果inputDataTable確實需要來自服務器端,那麼您需要使用可序列化的類型。我不知道究竟如何填寫您的數據對象在GeoMapData功能,但解決的辦法可能是定義inputDataTable如下:

let inputDataTable = [| 
    ("CN", 1234000, 9640821) 
    ("IN", 1133000, 3287263) 
    ("US", 304000, 9629091) 
    ("ID", 232000, 1904569) 
    ("BR", 187000, 8514877) 
    |] 

,然後在客戶端,這樣做:

let data = new Base.DataTable() 
data.addRows(inputDataTable) |> ignore 

訣竅是WebSharper表示在客戶端使用JavaScript數組的元組。而方法addRows,通常需要obj[][],也有一個過載,需要'T[]。這使您可以編寫上述正確類型的F#代碼,並將其編譯爲完全相同的JavaScript代碼,就像您傳遞obj[][]一樣。這個技巧用於this example(155行)。

+0

謝謝你的解釋。我想要有一個通用函數,以便我可以在地圖中添加儘可能多的系列(不是專門用於地理圖表,而是用於其他強度函數),這就是爲什麼我使用obj [ ] []而不是更直接的(string * double ...)[]。我會確保我不使用obj來繞過它。 – user1251614 2014-11-06 06:04:00