2012-06-09 6 views
2

Моя цель - создать данные для визуализации Google на сервере, а затем передать их клиенту как скрипт java, чтобы он отображался как линейную диаграмму. Мой пример ниже компилируется правильно, но создает ошибку при визуализации в браузере. Что мне нужно сделать, чтобы объект DataCommon правильно отображался как java-скрипт после его создания на сервере?Как создать данные для визуализации Google на сервере с помощью WebSharper

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() 

ответ

2

Ваша функция RandomData работает на сервере. Поэтому вы создаете объекты на сервере только для JavaScript DataTable - результат этого обычно не определен.

Вы должны:

  1. Марк функции на стороне сервера, который генерирует данные с [<Remote>].
  2. Переместить структуру пользовательского интерфейса на клиентский код, аннотированный [<JavaScript>].
  3. Вызовите удаленную функцию с клиентской стороны - это будет использовать AJAX для получения данных. Хорошей практикой является async.Return от вашей удаленной функции, чтобы не блокировать браузер.

Для получения дополнительной информации просмотрите страницу Remoting или соответствующий раздел руководства.

В качестве альтернативы вы можете передать данные конструктору своего объекта Control и получить к нему доступ от члена Body. Это позволит сериализовать данные во время генерации HTML и избежать необходимости вызова AJAX - это полезно для создания статических сайтов HTML, например.