如何使用WebSharper在服务器上为Google Visualizations生成数据

时间:2012-06-09 19:36:54

标签: f# websharper

我的目标是能够在服务器上为Google Visualizations生成数据,然后将其作为java脚本传递给客户端,以便将其呈现为折线图。下面的示例正确编译,但在浏览器中呈现时会产生错误。在服务器上构建DataScript后,我需要做些什么才能使DataCommon对象正确呈现为java脚本?

namespace Website

open System

type Action =
    | Test

module Page =
    open System.Web
    open IntelliFactory.WebSharper.Sitelets
    open IntelliFactory.WebSharper.Html

    let Page title body : Content<Action> =       
        PageContent (fun context -> 
            { Page.Default with
                Title = Some(title)
                Body = body context
            })

module Chart =
    open System

    open IntelliFactory.WebSharper
    open IntelliFactory.WebSharper.Html
    open IntelliFactory.WebSharper.Google
    open IntelliFactory.WebSharper.Google.Visualization
    open IntelliFactory.WebSharper.Google.Visualization.Base
    open IntelliFactory.WebSharper.EcmaScript

    open IntelliFactory.WebSharper.Web

    let RandomData () =

        let random = new Random()

        let valueCount = 100
        let maxValue = 300
        let seriesCount = random.Next(5)

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

        let addSeries index =
            let name = sprintf "Series %d" index
            data.addColumn(ColumnType.NumberType, name)
            |> ignore

            Seq.init valueCount (fun index -> random.Next(maxValue))
            |> Seq.iteri (fun valueIndex value -> data.setValue(index, valueIndex, value) |> ignore)

        [0 .. seriesCount]
        |> List.iter addSeries

        data        

    type LineChart( data : DataCommon, title ) =    
        inherit Web.Control()

        [<JavaScript>]
        override this.Body = 
            let div = 
                Div [] 
                |>! OnAfterRender (fun container ->
                    let visualization = new Visualizations.LineChart(container.Dom)
                    let options = {
                        Visualizations.LineChartOptions.Default with
                            width = 400.0
                            height = 240.0
                            legend = Visualizations.LegendPosition.Bottom
                            title = title
                    }
                    visualization.draw(data, options))
            div :> _

module Site =
    open Chart
    open Page

    open IntelliFactory.Html
    open IntelliFactory.WebSharper.Sitelets

    let TestPage =
        Page "Test" (fun (context : Context<Action>) -> 
        [
            Div [Text "Test"]
            Div [new Chart.LineChart(RandomData(), "Test Chart")]
        ])            

    let Main =
        Sitelet.Sum [
            Sitelet.Content "/" Test TestPage
        ]

open IntelliFactory.WebSharper.Sitelets
type Website() =    
    interface IWebsite<Action> with
        member this.Sitelet = Site.Main
        member this.Actions = [Test]

[<assembly: WebsiteAttribute(typeof<Website>)>]
do ()

1 个答案:

答案 0 :(得分:2)

您的RandomData功能在服务器上运行。因此,您正在服务器上构建仅限JavaScript的DataTable对象 - 执行此操作的结果通常是未定义的。

你应该:

  1. 使用[<Remote>]标记生成数据的服务器端函数。
  2. 将UI构造移至注释为[<JavaScript>]的客户端代码。
  3. 从客户端调用远程函数 - 这将使用AJAX来获取数据。优良作法是从远程功能async.Return开始,以免阻止浏览器。
  4. 查看Remoting页面或手册的相关部分以获取更多信息。

    或者,您可以将数据传递给Control对象的构造函数,并从Body成员访问它。这将在HTML生成期间序列化数据并避免需要AJAX调用 - 例如,这对于生成静态HTML站点很有用。