My app was working correctly until I decided to upgrade to om-alpha26.
Now I'm getting: Cannot read property 'force_children' of undefined
I have tried deleting my target folder and executing 'lein clean' to no avail.
Nothing comes up on google, I made no other code changes apart form updating the om version in my project.clj. I'm using chestnut as my development environment.
Here's my project.clj:
:source-paths ["src/clj"]
:test-paths ["test/clj"]
:dependencies [[org.clojure/clojure "1.7.0"]
[org.clojure/clojurescript "1.7.145" :scope "provided"]
[ring "1.4.0"]
[ring/ring-defaults "0.1.5"]
[slester/ring-browser-caching "0.1.1"]
[bk/ring-gzip "0.1.1"]
[compojure "1.4.0"]
[enlive "1.1.6"]
[org.omcljs/om "1.0.0-alpha26"]
[environ "1.0.0"]
[com.datomic/datomic-pro "0.9.5327"]
[liberator "0.13"]
[cljs-ajax "0.5.1"]
[clj-http "2.0.0"]
[org.apache.httpcomponents/httpclient "4.3.5"]
[org.clojure/data.json "0.2.6"]
[overtone/at-at "1.2.0"]
[com.cognitect/transit-clj "0.8.281"]
[com.cognitect/transit-cljs "0.8.225"]
[com.stuartsierra/component "0.2.3"]
[http-kit "2.1.19"]
[com.taoensso/sente "1.6.0"]
[reaver "0.1.2"]
[clj-time "0.11.0"]
[differ "0.2.1"]
]
:repositories [["my.datomic.com" {:url "https://my.datomic.com/repo"
:username ["******"]
:password ["****"]}]]
:plugins [[lein-cljsbuild "1.0.5"]
[lein-environ "1.0.0"]
[lein-auto "0.1.2"]]
:min-lein-version "2.5.0"
:uberjar-name "ngbc.jar"
:cljsbuild {:builds {:app {:source-paths ["src/cljs"]
:compiler {:output-to "resources/public/js/app.js"
:output-dir "resources/public/js/out"
:source-map "resources/public/js/out.js.map"
:preamble ["react/react.min.js"]
:optimizations :none
:pretty-print true}}}}
:profiles {:dev {:source-paths ["env/dev/clj"]
:test-paths ["test/clj"]
:dependencies [[figwheel "0.3.9"]
[figwheel-sidecar "0.5.0-2"]
[com.cemerick/piggieback "0.2.1"]
[org.clojure/tools.nrepl "0.2.10"]
[weasel "0.7.0"]]
:repl-options {:init-ns ngbc.server
:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}
:plugins [[lein-figwheel "0.3.9"]]
:figwheel {:http-server-root "public"
:server-port 3449
:css-dirs ["resources/public/css"]
:ring-handler ngbc.server/http-handler}
:env {:is-dev true
:browser-caching {"text/javascript" 0
"text/html" 0}}
:cljsbuild {:test-commands { "test" ["phantomjs" "env/test/js/unit-test.js" "env/test/unit-test.html"] }
:builds {:app {:source-paths ["env/dev/cljs"]}
:test {:source-paths ["src/cljs" "test/cljs"]
:compiler {:output-to "resources/public/js/app_test.js"
:output-dir "resources/public/js/test"
:source-map "resources/public/js/test.js.map"
:preamble ["react/react.min.js"]
:optimizations :whitespace
:pretty-print false}
:notify-command ["phantomjs" "bin/speclj" "resources/public/js/app_test.js"]
}}}}
:uberjar {:source-paths ["env/prod/clj"]
:hooks [leiningen.cljsbuild]
:env {:production true
:browser-caching {"text/javascript" 604800
"text/html" 0}}
:omit-source true
:aot :all
:main ngbc.server
:cljsbuild {:builds {:app
{:source-paths ["env/prod/cljs"]
:compiler
{:optimizations :whitespace
:pretty-print false}}}}}})
UPDATE:
The 'force_children' function is not one that I've defined. Following the stack trace it looks like it is being called on a (om.dom/div ....children). When I remove child nodes from the expression the code compiles, here's the code:
(defui RootView
static om/IQuery
(query [this]
(let [bonus-subquery (om/get-query Bonus)]
`[{:bonuses ~bonus-subquery}]))
Object
(render [this]
(let [{:keys [bonuses]} (om/props this)]
(dom/div nil <--- ERROR OCCURS HERE
(dom/header nil
(dom/div #js {:className "search-header"}
(dom/a #js {:className "logo"})))
(dom/ul #js {:className "simple-sidebar"}
(dom/li nil
(dom/div #js {:className "fa fa-gift"})))
(dom/div #js {:className "row no-margin main-container"}
(dom/div #js {:className "col-xs-12 no-padding"}
(dom/div #js {:className "artist-songs-container"}
#_(dom/input nil "Title")
#_(dom/input nil "Bonus")
(dom/h6 nil "My Bonuses")
(apply dom/div nil
[(dom/h3 nil "Collect")
(bonus-list-view
(sort-by-posted bonuses))]))))))))
I suspect it is to do with chestnut because the error doesn't occur when I upload the code to heroku. Here's the stack trace:
> Uncaught TypeError: Cannot read property 'force_children' of
> undefined(anonymous function) #
> core.cljs?rel=1450501232093:143
>
>ReactCompositeComponentMixin._renderValidatedComponentWithoutOwnerOrCont>ext#react.inc.js:5933
>
>ReactCompositeComponentMixin._renderValidatedComponent
> # react.inc.js:5953
>
wrapper #react.inc.js:12336
>
>ReactCompositeComponentMixin.mountComponent #
> react.inc.js:5566
>
>wrapper #
> react.inc.js:12336
>
>ReactReconciler.mountComponent #
> react.inc.js:12961
>
>ReactCompositeComponentMixin.mountComponent #
> react.inc.js:5571
>
>wrapper #
> react.inc.js:12336
>
>ReactReconciler.mountComponent #
> react.inc.js:12961
>
>mountComponentIntoNode #
> react.inc.js:10854
>
>Mixin.perform #
> react.inc.js:15613
>
>batchedMountComponentIntoNode #
> react.inc.js:10870
>
>Mixin.perform #
> react.inc.js:15613
>
>ReactDefaultBatchingStrategy.batchedUpdates #
> react.inc.js:8443
>
>batchedUpdates #
> react.inc.js:13689
>
>ReactMount._renderNewRootComponent #
> react.inc.js:11064
>
>wrapper #
> react.inc.js:12336
>
>ReactMount._renderSubtreeIntoContainer #
> react.inc.js:11133
>
>ReactMount.render # react.inc.js:11153wrapper #
> react.inc.js:12336
>
>(anonymous function) #
> next.cljs?rel=1447028869174:1236
>
>(anonymous function) #
> next.cljs?rel=1447028869174:1079
>
>(anonymous function) #
> next.cljs?rel=1447028869174:1090
>
>om.next.Reconciler.om$next$protocols$IReconciler$add_root_BANG_$arity$4
> # next.cljs?rel=1447028869174:1111
>
>om$next$protocols$add_root_BANG_ #
> protocols.cljs?rel=1447028869504:13
>
>om.next.add_root_BANG_.cljs$core$IFn$_invoke$arity$4
> # next.cljs?rel=1447028869174:660
>
>om$next$add_root_BANG_ #
> next.cljs?rel=1447028869174:647
>
>om.next.add_root_BANG_.cljs$core$IFn$_invoke$arity$3
> # next.cljs?rel=1447028869174:654
>
>om$next$add_root_BANG_ #
> next.cljs?rel=1447028869174:647
>
>ngbc$core$main #
> core.cljs?rel=1450501232093:240
>
>(anonymous function) #
> main.cljs?rel=1448073424172:14
>
>core.cljs?rel=1447680439306:164
Thanks!
Related
I'm following code examples from the book Web Development with Clojure, 3rd Edition. Currently running through the examples for using ClojureScript to create a single page application with Reagent and Ajax. The compiled Javascript runs fine until I try to send data from a form to the server. This is supposed to break, because I haven't added in any of the Ajax code to attach a csrf token to the post request, and the author wants to walk through how the js console can be used for logging in development, but it's not breaking as expected. I should receive something like this:
error:{:status 403,
:status-text "Forbidden",
:failure :error,
:response "<h1>Invalid anti-forgery token</h1>"}
I've made sure that I'm running up to date on all of my dependencies and plugins. I recently made the switch to Brave to test it out, I like it a lot, but I've run into a few issues like this, and when I test this out in Chrome, it runs correctly (breaks as expected).
This is the code I have in my core.cljs file:
(:require [reagent.core :as r]
[ajax.core :refer [GET POST]]))
(defn send-message!
[fields]
(POST "/message"
{:params #fields
:handler #(.log js/console (str "response:" %))
:error-handler #(.log js/console (str "error:" %))}))
(defn message-form
[]
(let [fields (r/atom {})]
(fn []
[:div
[:div.field
[:label.label {:for :name} "Name"]
[:input.input
{:type :text
:name :name
:on-change #(swap! fields assoc :name (-> % .-target .-value))
:value (:name #fields)}]]
[:div.field
[:label.label {:for :message} "Message"]
[:textarea.textarea
{:name :message
:value (:message #fields)
:on-change #(swap! fields assoc :message (-> % .-target .-value))}]]
[:input.button.is-primary
{:type :submit
:on-click #(send-message! fields)
:value "Comment"}]
[:p "Name: " (:name #fields)]
[:p "Message: " (:message #fields)]])))
(defn home
[]
[:div.content
[:div.column.is-centered
[:div.column.is-two-thirds
[:div.columns
[:div.column
[message-form]]]]]])
(r/render [home] (.getElementById js/document "content"))
When I open the page in Brave, I get these two messages upon loading:
undefined
at log.js:38
Uncaught TypeError: goog.log.getLogger is not a function
at xhrio.js:249
(anonymous) # xhrio.js:249
The Javascript still runs fine, but when I hit the "submit" button, I get these two errors, which I suspect might be in Google's Closure code? Not sure:
at goog.net.XhrIo.ajax$protocols$AjaxImpl$_js_ajax_request$arity$3 (xhrio.cljs:30)
at ajax$protocols$_js_ajax_request (protocols.cljc:6)
at ajax$simple$raw_ajax_request (simple.cljc:64)
at ajax$simple$ajax_request (simple.cljc:67)
at ajax$easy$easy_ajax_request (easy.cljc:116)
at Function.cljs$core$IFn$_invoke$arity$variadic (core.cljc:75)
at ajax$core$POST (core.cljc:75)
at guestbook$core$send_message_BANG_ (core.cljs:7)
at core.cljs:30
at HTMLUnknownElement.callCallback (react-dom.inc.js:341)
(anonymous) # xhrio.cljs:30
ajax$protocols$_js_ajax_request # protocols.cljc:6
ajax$simple$raw_ajax_request # simple.cljc:64
ajax$simple$ajax_request # simple.cljc:67
ajax$easy$easy_ajax_request # easy.cljc:116
(anonymous) # core.cljc:75
ajax$core$POST # core.cljc:75
guestbook$core$send_message_BANG_ # core.cljs:7
(anonymous) # core.cljs:30
callCallback # react-dom.inc.js:341
invokeGuardedCallbackDev # react-dom.inc.js:391
invokeGuardedCallback # react-dom.inc.js:448
invokeGuardedCallbackAndCatchFirstError # react-dom.inc.js:462
executeDispatch # react-dom.inc.js:594
executeDispatchesInOrder # react-dom.inc.js:616
executeDispatchesAndRelease # react-dom.inc.js:719
executeDispatchesAndReleaseTopLevel # react-dom.inc.js:727
forEachAccumulated # react-dom.inc.js:701
runEventsInBatch # react-dom.inc.js:744
runExtractedPluginEventsInBatch # react-dom.inc.js:875
handleTopLevel # react-dom.inc.js:6026
batchedEventUpdates # react-dom.inc.js:2342
dispatchEventForPluginEventSystem # react-dom.inc.js:6121
dispatchEvent # react-dom.inc.js:6150
unstable_runWithPriority # react.inc.js:2820
runWithPriority$2 # react-dom.inc.js:11443
discreteUpdates$1 # react-dom.inc.js:21810
discreteUpdates # react-dom.inc.js:2357
dispatchDiscreteEvent # react-dom.inc.js:6104
react-dom.inc.js:481
Uncaught TypeError: G__20367.setTimeoutInterval is not a function
at goog.net.XhrIo.ajax$protocols$AjaxImpl$_js_ajax_request$arity$3 (xhrio.cljs:30)
at ajax$protocols$_js_ajax_request (protocols.cljc:6)
at ajax$simple$raw_ajax_request (simple.cljc:64)
at ajax$simple$ajax_request (simple.cljc:67)
at ajax$easy$easy_ajax_request (easy.cljc:116)
at Function.cljs$core$IFn$_invoke$arity$variadic (core.cljc:75)
at ajax$core$POST (core.cljc:75)
at guestbook$core$send_message_BANG_ (core.cljs:7)
at core.cljs:30
at HTMLUnknownElement.callCallback (react-dom.inc.js:341)
(anonymous) # xhrio.cljs:30
ajax$protocols$_js_ajax_request # protocols.cljc:6
ajax$simple$raw_ajax_request # simple.cljc:64
ajax$simple$ajax_request # simple.cljc:67
ajax$easy$easy_ajax_request # easy.cljc:116
(anonymous) # core.cljc:75
ajax$core$POST # core.cljc:75
guestbook$core$send_message_BANG_ # core.cljs:7
(anonymous) # core.cljs:30
callCallback # react-dom.inc.js:341
invokeGuardedCallbackDev # react-dom.inc.js:391
invokeGuardedCallback # react-dom.inc.js:448
invokeGuardedCallbackAndCatchFirstError # react-dom.inc.js:462
executeDispatch # react-dom.inc.js:594
executeDispatchesInOrder # react-dom.inc.js:616
executeDispatchesAndRelease # react-dom.inc.js:719
executeDispatchesAndReleaseTopLevel # react-dom.inc.js:727
forEachAccumulated # react-dom.inc.js:701
runEventsInBatch # react-dom.inc.js:744
runExtractedPluginEventsInBatch # react-dom.inc.js:875
handleTopLevel # react-dom.inc.js:6026
batchedEventUpdates # react-dom.inc.js:2342
dispatchEventForPluginEventSystem # react-dom.inc.js:6121
dispatchEvent # react-dom.inc.js:6150
unstable_runWithPriority # react.inc.js:2820
runWithPriority$2 # react-dom.inc.js:11443
discreteUpdates$1 # react-dom.inc.js:21810
discreteUpdates # react-dom.inc.js:2357
dispatchDiscreteEvent # react-dom.inc.js:6104
Any ideas as to why this runs as expected in Chrome but not in Brave?
I am trying to recreate the example in http://react-component.github.io/table/examples/animation.html to add animation to a table in a re-frame app. The table is rendered using antizer which is a ClojureScript library for Ant Design react components. For the animation I'm trying to use rc-animate (as in the example) which is a JavaScript library.
To integrate rc-animate, I followed the official Webpack guide and created a src/js/index.js file:
import Animate from 'rc-animate';
window.Animate = Animate;
My project.clj is:
(defproject ant-table-animation "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.8.0"]
[org.clojure/clojurescript "1.10.238"]
[reagent "0.8.1"]
[re-frame "0.10.5" :exclusions [reagent]]
[antizer "0.3.1"]]
:plugins [[lein-cljsbuild "1.1.7"]]
:min-lein-version "2.5.3"
:source-paths ["src/clj" "src/cljs"]
:clean-targets ^{:protect false} ["resources/public/js/compiled" "target"]
:figwheel {:css-dirs ["resources/public/css"]}
:profiles
{:dev
{:dependencies [[binaryage/devtools "0.9.10"]
[cider/piggieback "0.3.9"]
[figwheel-sidecar "0.5.16"]
[day8.re-frame/re-frame-10x "0.3.3"]]
:plugins [[lein-figwheel "0.5.16"]]}
:prod { }
}
:cljsbuild
{:builds
[{:id "dev"
:source-paths ["src/cljs"]
:figwheel {:on-jsload "ant-table-animation.core/mount-root"}
:compiler {:closure-defines {re-frame.trace.trace_enabled_QMARK_ true}
:main ant-table-animation.core
:output-to "resources/public/js/compiled/app.js"
:output-dir "resources/public/js/compiled/out"
:asset-path "js/compiled/out"
:source-map-timestamp true
:preloads [devtools.preload, day8.re-frame-10x.preload]
:external-config {:devtools/config {:features-to-install :all}}
:infer-externs true
:npm-deps false
:foreign-libs [{:file "dist/index_bundle.js"
:provides ["rc-animate" "rc-animate-child"]
:global-exports {rc-animate Animate
rc-animate-child AnimateChild}}]
}}
{:id "min"
:source-paths ["src/cljs"]
:compiler {:main ant-table-animation.core
:output-to "resources/public/js/compiled/app.js"
:optimizations :advanced
:closure-defines {goog.DEBUG false}
:pretty-print false}}
]}
)
and in my views.cljs I try to render the table like this:
(ns ant-table-animation.views
(:require
[re-frame.core :as re-frame]
[ant-table-animation.subs :as subs]
[ant-table-animation.events :as events]
[antizer.reagent :as ant]
[reagent.core :as reagent]
[rc-animate]
))
(.log js/console rc-animate)
(defn AnimateBody
[props]
(.createElement
js/React
rc-animate
(.assign js/Object #js {:transitionName "move", :component "tbody"} props)))
(.log js/console AnimateBody)
(defn orders
[]
(let [orders #(re-frame/subscribe [::subs/orders])
width 80]
[ant/table
{:columns
[{:title "Product Name" :dataIndex :product :width width}
{:title "Quantity" :dataIndex :quantity :width width}
{:title "Unit Price" :dataIndex :price :width width}
{:title "Actions" :dataIndex "actions" :width width
:render
#(reagent/as-element
[ant/button
{:icon "delete" :type "danger"
:on-click
(fn []
(re-frame/dispatch [::events/order-deleted (.-product %2)]))}])}]
:dataSource orders
:size "small"
:components {:body {:wrapper AnimateBody}}
:pagination {:page-size 20}
:scroll {:y 300}}]))
(defn main-panel []
(let [name (re-frame/subscribe [::subs/name])]
[:div
[:h1 "Hello from " #name]
[orders]
]))
I am not sure at all about the
(defn AnimateBody
[props]
(.createElement
js/React
rc-animate
(.assign js/Object #js {:transitionName "move", :component "tbody"} props)))
being equivalent to the line from the example
const AnimateBody = props => <Animate transitionName="move" component="tbody" {...props} />;
The table renders correctly, but when I try to delete a row it fails with the following error trace:
react-dom.development.js:55 Uncaught Error: Unable to find node on an unmounted component.
at invariant (react-dom.development.js:55)
at findCurrentFiberUsingSlowPath (react-dom.development.js:4256)
at findCurrentHostFiber (react-dom.development.js:4266)
at findHostInstance (react-dom.development.js:17676)
at Object.findDOMNode (react-dom.development.js:18145)
at AnimateChild.transition (AnimateChild.js:83)
at AnimateChild.componentWillLeave (AnimateChild.js:70)
at performLeave (Animate.js:339)
at Array.forEach (<anonymous>)
at Animate.componentDidUpdate (Animate.js:188)
at commitLifeCycles (react-dom.inc.js:15386)
at commitAllLifeCycles (react-dom.inc.js:16646)
at HTMLUnknownElement.callCallback (react-dom.inc.js:143)
at Object.invokeGuardedCallbackDev (react-dom.inc.js:193)
at invokeGuardedCallback (react-dom.inc.js:250)
at commitRoot (react-dom.inc.js:16800)
at completeRoot (react-dom.inc.js:18192)
at performWorkOnRoot (react-dom.inc.js:18120)
at performWork (react-dom.inc.js:18024)
at performSyncWork (react-dom.inc.js:17996)
at requestWork (react-dom.inc.js:17884)
at scheduleWork (react-dom.inc.js:17689)
at Object.enqueueForceUpdate (react-dom.inc.js:11855)
at Object.Component.forceUpdate (react.inc.js:479)
at reagent$impl$batching$run_queue (batching.cljs?rel=1541330682770:39)
at Object.flush_queues (batching.cljs?rel=1541330682770:86)
at Object.run_queues (batching.cljs?rel=1541330682770:76)
at batching.cljs?rel=1541330682770:63
at re_frame_10x.cljs?rel=1541164419576:125
It is also indicated that:
The above error occurred in the <Animate> component:
in Animate (created by ant_table_animation.views.animateBody)
in ant_table_animation.views.animateBody (created by BaseTable)
in table (created by BaseTable)
in BaseTable (created by Connect(BaseTable))
in Connect(BaseTable) (created by BodyTable)
in div (created by BodyTable)
in BodyTable (created by ExpandableTable)
in div (created by ExpandableTable)
in div (created by ExpandableTable)
in div (created by ExpandableTable)
in ExpandableTable (created by Connect(ExpandableTable))
in Connect(ExpandableTable) (created by Table)
in Provider (created by Table)
in Table (created by LocaleReceiver)
in LocaleReceiver (created by Table)
in div (created by Spin)
in AnimateChild (created by Animate)
in div (created by Animate)
in Animate (created by Spin)
in Spin (created by Table)
in div (created by Table)
in Table (created by ant_table_animation.views.orders)
in ant_table_animation.views.orders (created by ant_table_animation.views.main_panel)
in div (created by ant_table_animation.views.main_panel)
in ant_table_animation.views.main_panel
I am a Clojure beginner, and I know even less for React; this is where I ended up after a week of trying but now I feel stuck. I have uploaded my project in github for anyone that would like to give it a try.
The Unable to find node on an unmounted component error was occurring because of version issues with React. I was able to handle it by explicitly using the version of React used by the rc-animate library - 16.5.2 in my project.clj:
...
[reagent "0.8.1" :exclusions [cljsjs/react cljsjs/react-dom [cljsjs/react-dom-server]]]
[cljsjs/react "16.5.2-0"]
[cljsjs/react-dom "16.5.2-0"]
[cljsjs/react-dom-server "16.5.2-0"]
...
[antizer "0.3.1" :exclusions [cljsjs/react cljsjs/react-dom [cljsjs/react-dom-server]]]]
...
For the correct definition of the AnimateBody component I had to use a combination of reagent/adapt-react-class, reagent/as-element and reagent/reactify-component.
Specifically, in my views.cljs I define the component as:
(def animate (reagent/adapt-react-class rc-animate))
(def animateBody
(fn [props]
(reagent/as-element [animate (assoc props :transition-name "move" :component "tbody")])))
and then pass it to the ant/table component with:
...
:components {:body {:wrapper (reagent/reactify-component animateBody)}}
...
I am trying to learn clojurescript by building a desktop application. The boot configuration I am working with as follows:
(def +name+ "visivo/desktop")
(def +version+ "0.0.1-SNAPSHOPT")
(def +description+ "Desktop application for visivo")
(def +repository+ "https://gitlab.com/visivo/desktop")
(set-env!
:source-paths #{"src/cljs"}
:resource-paths #{"resources"}
:dependencies '[
[org.clojure/clojure "1.9.0-alpha20"]
[org.clojure/clojurescript "1.9.908"]
[org.clojure/tools.nrepl "0.2.12" :scope "test"]
[com.cemerick/piggieback "0.2.2" :scope "test"]
[weasel "0.7.0" :scope "test"]
[adzerk/boot-cljs "2.1.3" :scope "test"]
[adzerk/boot-cljs-repl "0.3.3" :scope "test"]
[adzerk/boot-reload "0.5.2" :scope "test"]
[proto-repl "0.3.1" :scope "test"]
[proto-repl-charts "0.3.2" :scope "test"]
[boot-codox "0.10.3" :scope "test"]])
(require
'[adzerk.boot-cljs :refer [cljs]]
'[adzerk.boot-cljs-repl :refer [cljs-repl start-repl]]
'[adzerk.boot-reload :refer [reload]]
'[codox.boot :refer [codox]])
(task-options!
pom {:project 'visivo/desktop
:version +version+
:description +description+
:url +repository+
:scm {:url +repository+}
:license {"Eclipse Public License"
"http://www.eclipse.org/legal/epl-v10.html"}})
(deftask prod []
(comp (cljs :ids #{"main"}
:optimizations :advanced)
(cljs :ids #{"renderer"}
:optimizations :advanced)))
(deftask dev []
(comp
(speak)
(watch)
(cljs-repl :ids #{"renderer"})
(reload :ids #{"renderer"}
:ws-host "localhost"
:on-jsload 'visivo.renderer/init
:target-path "target")
(cljs :ids #{"renderer"})
(cljs :ids #{"main"}
:compiler-options {:asset-path "target/main.out"
:closure-defines {'visivo.main/dev? true}})
(target)))
(deftask docs []
"Generates documentation for the project from comments"
(comp (codox
:name +name+
:description +description+
:version +version+
:language :clojurescript
:output-path ".")
(target :dir #{"docs"})))
I am willing to add a task to run figwheel. But before doing that I wanted to know whats the difference between using figwheel and (watch and reload) functions as described in dev task?
Here's some quotes about the differences between the two:
figwheel -> https://github.com/adzerk-oss/boot-reload It's not as smart as figwheel because u can lose state, but it's mostly enough. We are actually quite fine with reloading the page manually most of the time.
Figwheel has more bells and whistles but the core functionality should be very similar -- martinklepsch
Figwheel at it's core is the same as what boot-reload can do for you if you develop a Hoplon app
I've been following tutorial at https://anmonteiro.com/2017/03/requiring-node-js-modules-from-clojurescript-namespaces/ to use Clojurescript's :npm-deps feature.
Using left-pad works well, but when I tried to use bignumber.js I've hit problems.
This is from my project.clj
{:main "npm-deps-test.core"
:output-to "dev-compiled/npm-deps-test.js",
:output-dir "dev-compiled",
:target :nodejs,
:optimizations :none,
:source-map true
:npm-deps {:bignumber.js "4.0.2"
:left-pad "1.1.3"}}
This is code with output:
(ns npm-deps-test.core
(:require [left-pad]
[bignumber.js :as bignumber]))
(enable-console-print!)
(comment
(type bignumber)
; => #object[Object "function Object() { [native code] }"]
(aget bignumber "__proto__" "constructor")
; => #object[Object "function Object() { [native code] }"]
(bignumber "123")
; #object[TypeError TypeError: module$Users$matus$www$clojure_hacking$npm_deps_test$node_modules$bignumber_js$bignumber is not a function]
; => nil
(new bignumber "124")
; #object[TypeError TypeError: module$Users$matus$www$clojure_hacking$npm_deps_test$node_modules$bignumber_js$bignumber is not a constructor]
; => nil
(bignumber. "123")
; #object[TypeError TypeError: module$Users$matus$www$clojure_hacking$npm_deps_test$node_modules$bignumber_js$bignumber is not a constructor]
; => nil
(left-pad 42 5 0)
; => 00042
)
Any idea why this doesn't work as expected?
Using [org.clojure/clojurescript "1.9.671"]
[lein-figwheel "0.5.11"]
This works for me in the ClojureScript REPL when using [org.clojure/clojurescript "1.9.562"]
user=> (require '[bignumber.js :as BigNumber])
nil
user=> (BigNumber. "123")
#object[BigNumber 123]
user=> (-> (BigNumber. "12345678") (.toExponential))
"1.2345678e+7"
I would guess that the behaviour you're seeing could be a bug or breaking change in [org.clojure/clojurescript "1.9.671"].
Update:
This does indeed appear to be a bug that was patched today:
https://github.com/clojure/clojurescript/commit/00df4ae8a49005dbbb3ad87bf1a24e71897d74f7
I would suggest that you downgrade to an older (but recent!) version of ClojureScript e.g. [org.clojure/clojurescript "1.9.562"] until there is a new release which includes this patch.
I have two files, one html and one css. I have tried to turn them into a heroku app and even used the lein command to create a heroku friendly skeleton and plug these two files in, but cannot get it to work for the life of me. There is something very basic that I don't yet understand about how to coordinate a view with the back-end control. And the hello world tutorials aren't helping me because they do not show me how to do different things or explain what needs to change in my defroutes function, for example, for that to be accomplished. In short, my question is this: How can I coordinate these two files into a Clojure project to make the html render as the front page of a webapp and then deploy it on heroku?
html:
<html>
<head>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<img id="sun" src="http://goo.gl/dEEssP">
<div id='earth-orbit'>
<img id="earth" src="http://goo.gl/o3YWu9">
</div>
</body>
</html>
web.clj file in "lein new heroku ..." project:
(ns solar_system.web
(:require [compojure.core :refer [defroutes GET PUT POST DELETE ANY]]
[compojure.handler :refer [site]]
[compojure.route :as route]
[clojure.java.io :as io]
[ring.middleware.stacktrace :as trace]
[ring.middleware.session :as session]
[ring.middleware.session.cookie :as cookie]
[ring.adapter.jetty :as jetty]
[ring.middleware.basic-authentication :as basic]
[cemerick.drawbridge :as drawbridge]
[environ.core :refer [env]]))
(defn- authenticated? [user pass]
;; TODO: heroku config:add REPL_USER=[...] REPL_PASSWORD=[...]
(= [user pass] [(env :repl-user false) (env :repl-password false)]))
(def ^:private drawbridge
(-> (drawbridge/ring-handler)
(session/wrap-session)
(basic/wrap-basic-authentication authenticated?)))
(defroutes app
(ANY "/repl" {:as req}
(drawbridge req))
(GET "/" []
{:status 200
:headers {"Content-Type" "text/plain"}
:body (pr-str ["Hello" :from 'Heroku])}) ; <= Should I change this part here?
(ANY "*" []
(route/not-found (slurp (io/resource "404.html")))))
(defn wrap-error-page [handler]
(fn [req]
(try (handler req)
(catch Exception e
{:status 500
:headers {"Content-Type" "text/html"}
:body (slurp (io/resource "500.html"))}))))
(defn -main [& [port]]
(let [port (Integer. (or port (env :port) 5000))
;; TODO: heroku config:add SESSION_SECRET=$RANDOM_16_CHARS
store (cookie/cookie-store {:key (env :session-secret)})]
(jetty/run-jetty (-> #'app
((if (env :production)
wrap-error-page
trace/wrap-stacktrace))
(site {:session {:store store}}))
{:port port :join? false})))
;; For interactive development:
;; (.stop server)
;; (def server (-main))
project.clj file
(defproject solar_system "1.0.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://solar_system.herokuapp.com"
:license {:name "FIXME: choose"
:url "http://example.com/FIXME"}
:dependencies [[org.clojure/clojure "1.4.0"]
[compojure "1.1.1"]
[ring/ring-jetty-adapter "1.1.0"]
[ring/ring-devel "1.1.0"]
[ring-basic-authentication "1.0.1"]
[environ "0.2.1"]
[com.cemerick/drawbridge "0.0.6"]]
:min-lein-version "2.0.0"
:plugins [[environ/environ.lein "0.2.1"]]
:hooks [environ.leiningen.hooks]
:profiles {:production {:env {:production true}}})
example of typical handler code that renders text:
(ns hello-world.core
(:use ring.adapter.jetty))
(defn app [req]
{:status 200
:headers {"Content-Type" "text/plain"}
:body "Hello, world"}) ; <= Could I just change this part to slurp in
; the html file and stick it in a file in my
; root directory to get a successful 'git push heroku master'?
Modifying your code:
(defroutes app
(ANY "/repl" {:as req}
(drawbridge req))
(GET "/" []
{:status 200
:headers {"Content-Type" "text/html"} ; change content type
:body (slurp "resources/public/my-file.html")}) ; wherever your file is
(ANY "*" []
(route/not-found (slurp (io/resource "404.html")))))
How I'd write it:
(defroutes app
(ANY "/repl" {:as req} (drawbridge req))
(GET "/" [] (slurp "resources/public/my-file.html")) ; wherever your file is
(route/resources "/") ; special route for serving static files like css
; default root directory is resources/public/
(route/not-found (slurp (io/resource "404.html")))) ; IDK what io/resource does
; you might not need it