【问题标题】:Websharper / Web.Control constructor issueWebsharper / Web.Control 构造函数问题
【发布时间】:2014-11-06 08:02:08
【问题描述】:

在想自定义 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 数组不会造成任何问题。

有人知道发生了什么吗?

感谢您的见解。

【问题讨论】:

    标签: f# websharper


    【解决方案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 数组表示元组。并且通常采用obj[][] 的方法addRows 也有采用'T[] 的重载。这允许您编写上面正确键入的 F# 代码,并且它编译成与您传递 obj[][] 完全相同的 JavaScript 代码。这个技巧用在this example(第155行)中。

    【讨论】:

    • 感谢您的解释。我想要一个通用函数,这样我就可以在地图上添加尽可能多的系列(不是专门针对地理图表,而是针对其他人,例如强度图),这就是我使用 obj[ ][] 而不是更直接的 (string * double ...)[]。我会确保我不使用 obj 来绕过它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多