Google Chart CLJS Clojure

时间:2017-08-30 16:17:30

标签: clojure clojurescript reagent re-frame

我尝试在Google Chart中调整此example。致re-frame框架,reagent。我想基于订阅创建一个实时图表。我用一个简单的计数器测试= + - 1。

我收到错误:Assert failed: Render must be a function, not nil (ifn? render-fun)

(defn draw-demo-chart 
   [d]
   (let [[columns vectors options chart] (r/children d)
         data (new js/google.visualization.DataTable)]
       (doall ;gotta keep the doall on maps. lazy sequence...
      (map (fn [[type name]]
            (.addColumn data type name)) columns))
      (.addRows data vectors)
      (.draw chart data options)
      (.load js/google "visualization" "1" (clj->js {:packages ["corechart" "orgchart" "calendar" "map" "geochart"]}))     
      (.setOnLoadCallback js/google draw-demo-chart)
      ))


(defn draw-demo-chart-container
    []
    (let [count    (re-frame/subscribe [:count])
          columns  (reaction [["date" "X"] ["number" "Y"]])
          vectors  (reaction (clj->js [[(new js/Date "07/11/14") 145] [(new js/Date "07/12/14") 15]
                                      [(new js/Date "07/13/14") 23] [(new js/Date "07/14/14") 234]]))
          options  (reaction (clj->js {:title (str @count)}))
          chart    (reaction (new js/google.visualization.LineChart (.getElementById js/document "linechart"))) ]
     (fn []
        [draw-demo-graph @columns @vectors @options @chart])))

(def draw-demo-graph 
       (r/create-class {:reagent-render  draw-demo-chart
                        :component-did-mount draw-demo-chart
                        :component-did-update draw-demo-chart}))

1 个答案:

答案 0 :(得分:5)

使用Google Charts API存在一些挑战:

  1. 它以异步方式加载,只能在准备就绪时使用。
  2. 我建议使用一个标志来记录API是否准备就绪,即使在安装组件后加载API,也会允许它进行渲染。

    (defonce ready?
      (reagent/atom false))
    
    (defonce initialize
      (do
        (js/google.charts.load (clj->js {:packages ["corechart"]}))
        (js/google.charts.setOnLoadCallback
          (fn google-visualization-loaded []
            (reset! ready? true)))))
    
    1. 您需要在HTML元素上调用draw
    2. HTML元素仅在组件已安装时才存在。您可以使用ref方便地获取HTML元素(否则您需要保存对on的引用,或者搜索它)。

      (defn draw-chart [chart-type data options]
        [:div
         (if @ready?
           [:div
            {:ref
             (fn [this]
               (when this
                 (.draw (new (aget js/google.visualization chart-type) this)
                        (data-table data)
                        (clj->js options))))}]
           [:div "Loading..."])])
      

      您希望在任何输入发生变化时重绘(上述ref示例所做的事情)。

      1. 设置数据源
      2. 我建议一种获取数据源的便捷方法:

        (defn data-table [data]
          (cond
            (map? data) (js/google.visualization.DataTable. (clj->js data))
            (string? data) (js/google.visualization.Query. data)
            (seqable? data) (js/google.visualization.arrayToDataTable (clj->js data))))
        
        1. 使用它
        2. 现在您可以将图表用于反应值!

          [draw-chart
              "LineChart"
              @some-data
              {:title (str "Clicks as of day " @day)}]
          

          完整代码列表位于 https://github.com/timothypratley/google-chart-example