2

我的目标是能够在服务器上为 Google Visualizations 生成数据,然后将其作为 java 脚本传递给客户端,以便将其呈现为折线图。我下面的示例编译正确,但在浏览器中呈现时会产生错误。在服务器上构建 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 ()
4

1 回答 1

2

您的RandomData函数在服务器上运行。因此,您正在服务器上构建纯 JavaScriptDataTable对象 - 这样做的结果通常是未定义的。

你应该:

  1. 用 标记生成数据的服务器端函数[<Remote>]
  2. 将 UI 构造移至带注释的客户端代码[<JavaScript>]
  3. 从客户端调用远程函数——这将使用 AJAX 来获取数据。最好使用async.Return远程功能,以免阻止浏览器。

查看远程处理页面或手册的相关部分以获取更多信息。

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

于 2012-06-09T19:49:19.780 回答