Websharper / Web.Control构造函数问题

时间:2014-11-05 16:52:59

标签: f# websharper

虽然想要自定义Google DataVisualization,但我想参数化控件的构造函数,但由于某些原因,当我将inputDataTable作为参数传递时,它似乎无法工作。

这是我使用的默认数据:

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 个答案:

答案 0 :(得分:1)

传递给Web.Control的构造函数的值是在服务器端构造页面期间序列化为JSON的服务器端值。但是,类型obj没有序列化程序,因此inputDataTable(类型obj[][])的序列化失败。相反,在有效的版本中,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行)。

相关问题