reactjs


How to correctly wrap Google Closure UI Component as Rum Component


I would like to use Google Closure UI components from ClojureScript with the Rum/React library.
I started with goog.ui.DatePicker, but still cannot wrap it correctly. The code underneath renders the DatePicker once on component mount and at the right place, the event listener works and all is fine, except it needs the statically set id ("here") at the dom node to work which would be acceptable for one time hack, but not when I need to have the component wrapped and use several times on the same page/app.
(ns redux.components
(:require [rum.core :as r]
[cljs-time.core :as time]
[cljs-time.format :as tf]
[goog.dom :as dom]
[goog.ui.DatePicker :as goog-picker]
[goog.events :as goog-events]]))
(r/defcs +published-at < { :did-mount (fn [state]
(let [target-node (:r/ref state "here")
dp (goog.ui.DatePicker. nil goog.i18n.DateTimeSymbols_cs)]
(.listen dp (.. goog.ui.DatePicker -Events -CHANGE) #(println "new date is: " (tf/unparse (tf/formatter "YYYY-MM-dd")(time/to-default-time-zone (.. % -target getDate)))))
(.render dp (goog.dom/getElement "here")))
state) }
[]
[:div#here])
(r/defc app
[]
[:div
[:h1 "title"
(+published-at)]])
My further unsuccessful research
React documentation suggests that for integration with third-party DOM libraries one might need refs. Rum documentation describes how to do react refs from Rum. But the trouble is that React doc states that string refs are legacy and might be removed in future releases while Rum documentation does not cover callback based refs. I tried to guess how to combine both frameworks with string refs as well as callback refs, but neither one seems to work:
String based legacy approach
(r/defcs +published-at < { :did-mount (fn [state]
(let [target-node (:r/ref state "here")
dp (goog.ui.DatePicker. nil goog.i18n.DateTimeSymbols_cs)]
(.listen dp (.. goog.ui.DatePicker -Events -CHANGE) #(println (tf/unparse (tf/formatter "YYYY-MM-dd")(time/to-default-time-zone (.. % -target getDate)))))
(.render dp target-node))
state) }
[]
[:div
[:div { :ref "here" } ]])
This fails with error and the DatePicker is not even displayed:
Uncaught TypeError: opt_parentElement.insertBefore is not a function
at goog.ui.DatePicker.goog.ui.Component.render_ (component.js:705)
at goog.ui.DatePicker.goog.ui.Component.render (component.js:659)
at Function.<anonymous> (components.cljs?rel=1493075625598:123)
at Function.cljs.core.apply.cljs$core$IFn$_invoke$arity$3 (core.cljs:3694)
at cljs$core$apply (core.cljs:3676)
at util.cljc?rel=1492772300984:17
at core.cljs:2314
at Function.cljs.core.seq_reduce.cljs$core$IFn$_invoke$arity$3 (core.cljs:2314)
at cljs.core.LazySeq.cljs$core$IReduce$_reduce$arity$3 (core.cljs:3287)
at Function.cljs.core.reduce.cljs$core$IFn$_invoke$arity$3 (core.cljs:2358)
Callback base approach
(r/defcs +published-at < { :did-mount (fn [state]
(let [dp (goog.ui.DatePicker. nil goog.i18n.DateTimeSymbols_cs)]
(.listen dp (.. goog.ui.DatePicker -Events -CHANGE) #(println (tf/unparse (tf/formatter "YYYY-MM-dd")(time/to-default-time-zone (.. % -target getDate)))))
(.render dp (::put-date-here state)))
state) }
[state]
[:div
[:div { :ref #(assoc state ::put-date-here %) }]])
This renders functional DatePicker, but out of the component, at the end of the page.
You don't need :did-mount here, just render it right in the callback. This works fine for me:
(defn show-datepicker
[d]
(let [dp (goog.ui.DatePicker. nil goog.i18n.DateTimeSymbols_cs)]
(.listen dp (.. goog.ui.DatePicker -Events -CHANGE)
#(js/console.info
(.. % -target getDate)))
(.render dp d)))
[:div {:ref show-datepicker}]
If you need to tear down the datepicker then just check for (nil? d) in your show-datepicker. React will pass nil when the component unmounts.
PS: I wound't use cljs-time unless you really like big js output files.

Related Links

react+redux reducer handling with null
Removing and putting new contents in a component of React JS
Subclassing react components, HOC or classic OO?
Nested Match routes with React Router v4 and MatchWithFade
In React with Redux, when should I save data to back end
Can shouldComponentUpdate returning false clobber a previous update where shouldComponentUpdate returns true?
Passing className prop to Material-ui child/inner elements
Code splitting using webpack for example https://github.com/erikras/react-redux-universal-hot-example
Reactjs calender picker
React with sort and filter
Reactjs not rendering to HTML in Ubuntu 14
Test text input with react and jest
How do I add an image to the DOM after another image has loaded?
why is this.state.records.amount undefined?
How to upload file on server with react, redux
Diagnostics feature in Angular 2 vs React

Categories

HOME
airflow
indexing
google-cloud-pubsub
swift3
azure-documentdb
primefaces
pelican
xamarin.forms
apache-storm
highmaps
livecharts
query-string
crash
download
powerquery
vsixmanifest
token
mongoimport
aspectj
unreal-engine4
adroitlogic
opengrok
aggregate
webseal
sha1
exchange-transport-agents
google-closure-compiler
pylint
accordion
passbook
project-structure
coccinelle
fibonacci
lotusscript
javaagents
ng-tags-input
inline-assembly
ppp
suitescript
meteor-accounts
git-submodules
spock
apm
visual-prolog
oracle-nosql
availability
cache-control
kofax
multi-user
outlook-2010
framebuffer
pygraphviz
libconfig
origami
armadillo
delphi-xe
risc
infovis
automapper-4
flask-socketio
openxava
htop
multi-targeting
blackberry
petapoco
stripes
x12
networkstream
altova
boost-bind
transaction-isolation
clique
abstract
nonblocking
bioconductor
ruby-1.8.7
exchange-server-2007
vanilla-forums
web-standards
stereotype
waterline
gmaps4jsf
pymol
xmla
indices
esri-arc-engine
iphone-6
mind-manager
worklight-appcenter
behance-api
jsmpp
autofilter
mencoder
octokit
nsnumber
leap-year
panelgrid
gwt2
cloudmade
boost.build
linqdatasource
report-viewer2010
jquery-1.8
reflexil
parsec
advanceddatagrid
pinchzoom
utm
code-organization
jqtransform
azure-appfabric
arraycollection
script-tag
opengl-to-opengles
user-preferences

Resources

Encrypt Message