Josh.F
Josh.F

Reputation: 3806

In ClojureScript, how do I properly use cljsjs/react-mdl?

I've really been struggling with cljsjs libraries, and I've probably spent 2 full days worth of my life playing with the interop of react-bootstrap, and various material libraries in clojurescript.

Basically, I just want to be able to get UI components into my ClojureScript projects. If you can recommend something better than cljsjs/react-mdl, I'd love it. If you know how to help with my current bugs, I'd love that too!

I currently have:

(ns project.views
  (:require [cljsjs.react-mdl]))

(def Button (aget js/ReactMDL "Button"))

And I get the error:

ReactMDL is not defined

in the javascript console.

I just want to get one react-mdl button showing on the screen.

I'm using this wrapper: https://github.com/cljsjs/packages/tree/master/react-mdl

For this library: https://github.com/tleunen/react-mdl

And these interop instructions on cljsjs: https://github.com/cljsjs/packages/wiki/Using-Packages

I'm also using clojure's reagent, and reframe, if that matters. Honestly, I just want to get some project out the door built with Clojure and relevant libs, if you can recommend I use a different stack, please do!

Am I just overlooking something simple?

Upvotes: 4

Views: 1590

Answers (3)

Yuri G.
Yuri G.

Reputation: 86

This is how I made react-mdl work with Reagent.

Client app code

Require packages in project.clj:

[reagent "0.6.0" :exclusions [cljsjs/react]]
[cljsjs/react-with-addons "15.3.1-0"]
[cljsjs/react-mdl "1.5.4-0"]

Require in namespace:

(ns ,,,
 (:require  ,,,
            [cljsjs.react-mdl]))

Create helpers for components you'll use:

(def Button (.-Button js/ReactMDL))
(def Slider (.-Slider js/ReactMDL))
,,,

Now they can be used in Reagent views like this:

[:> Button "Hello!"]
[:> Slider {:min 0 :max 10}]

Server app code

react-mdl CSS file and Material UI icons should be included into HTML.

The CSS file is embedded inside cljsjs/react-mdl package. To extract it I used ring-cljsjs middleware:

; Add dependencies to project.clj
[ring-cljsjs "0.1.0"]
[cljsjs/react-mdl "1.5.4-0"]

; Apply middleware to the Ring handler
(ns app.handler
  (:require ,,,
            [ring.middleware.cljsjs :refer [wrap-cljsjs]]))
,,, 
(-> ,,,
   wrap-cljsjs)

; Add link to CSS into Hiccup template for the served HTML file
(ns ,,,
  (:require ,,,
            [hiccup.page :as h]))
,,,
[:head
  [:meta {:charset "UTF-8"}]
  [:meta {:name "viewport" :content "width=device-width, initial-scale=1"}]

  (h/include-css "/cljsjs/react-mdl/material.min.css")
  ,,,

Other ways of extracting non JS assets from cljsjs packages are described in the project's wiki.

Upvotes: 1

nha
nha

Reputation: 18005

It should be used like that :

(js/MaterialCheckbox element)
(js/MaterialDataTable ...)
;; and so on

You still need to require it in order to import the js and css files (that is all it does really). It threw me off at first too (when I was packaging it for cljsjs).

This is because react-mdl exposes objects through the global scope, for instance see https://github.com/tleunen/react-mdl/blob/master/extra/material.js#L701

Note : you could just use the css for some objects, like @Chris Murphy answer, but the point of react-mdl (instead of mdl) it to manage the lifecycle when needed as a react component. Otherwise you would just need mdl (which is completely fine). It may not matter for a simple button though.

Upvotes: 1

Chris Murphy
Chris Murphy

Reputation: 6509

I'll just answer getting a button going.

I didn't use any cljs libraries. I just used the css and the js as supplied. They need to be in your markup, and as well a link to the Material Design icons library.

This is the example in Reagent:

[:input {:type "submit"
:className "mdl-button mdl-js-button mdl-button--fab mdl-js-ripple-effect mdl-button--colored"
:value "ok"}]

And this in Om Next:

(defui MDSubmitButton
  Object
  (render [this]
    (dom/button (clj->js {:className "mdl-button mdl-js-button mdl-button--fab mdl-js-ripple-effect mdl-button--colored"})
                (dom/i (clj->js {:className "material-icons"}) "add"))))
(def md-submit-button (om/factory MDSubmitButton {:keyfn :id}))

I'm quite new to all this, but my preference is to just use css, keep the Javascript to a minimum, and then build components manually in whatever React wrapper the project is using.

Upvotes: 2

Related Questions