Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save madvas/5db418a60025d74acd1aa17339bdb894 to your computer and use it in GitHub Desktop.
Save madvas/5db418a60025d74acd1aa17339bdb894 to your computer and use it in GitHub Desktop.
Snippet example of using library cljs-react-material-ui with Reagent
(ns crmui-reagent.core
(:require
[cljsjs.material-ui]
[cljs-react-material-ui.core :as ui]
[cljs-react-material-ui.reagent :as rui]
[cljs-react-material-ui.icons :as ic]
[reagent.core :as r :refer [atom]]
[reagent.session :as session]
[secretary.core :as secretary :include-macros true]
[accountant.core :as accountant]
))
(enable-console-print!)
(defn my-component []
(r/create-class
{:component-did-mount #(println "component-did-mount")
:display-name "my-component"
:reagent-render (fn []
[rui/paper "My component"])}))
(defn some-other-component [text]
[rui/paper text])
;; -------------------------
;; Views
(defn user-menu []
(r/create-class
{:component-did-mount #(println "user-menu-did-mount")
:display-name "user-menu"
:reagent-render (fn []
[rui/icon-menu {:icon-button-element (ui/icon-button {:touch true} (ic/navigation-expand-more))}
[rui/menu-item {:primary-text "Edit Profile"}]
[rui/menu-item {:primary-text "Logout"}]])}))
(defn home-page []
(r/create-class
{:component-did-mount
#(println "home-page did mount")
:reagent-render
(fn []
[rui/mui-theme-provider
{:mui-theme (ui/get-mui-theme
{:palette {:text-color (ui/color :green600)}})}
[:div
[rui/app-bar {:title "Title"
:icon-element-right (ui/icon-button
(ic/action-account-balance-wallet))}]
[rui/paper
[user-menu]
[:div "Hello there"]
[my-component]
[some-other-component "What time is it?"]
[rui/mui-theme-provider
{:mui-theme (ui/get-mui-theme {:palette {:text-color (ui/color :blue200)}})}
[rui/raised-button {:label "Blue button"}]]
(ic/action-home {:color (ui/color :grey600)})
[rui/raised-button {:label "Click me"
:icon (ic/social-group)
:on-touch-tap #(println "clicked")}]]]])}))
(defn about-page []
[:div [:h2 "About crmui-reagent"]
[:div [:a {:href "/"} "go to the home page"]]])
(defn current-page []
[:div [(session/get :current-page)]])
;; -------------------------
;; Routes
(secretary/defroute "/" []
(session/put! :current-page #'home-page))
(secretary/defroute "/about" []
(session/put! :current-page #'about-page))
;; -------------------------
;; Initialize app
(defn mount-root []
(r/render [current-page] (.getElementById js/document "app")))
(defn init! []
(accountant/configure-navigation!
{:nav-handler
(fn [path]
(secretary/dispatch! path))
:path-exists?
(fn [path]
(secretary/locate-route path))})
(accountant/dispatch-current!)
(mount-root))
@binarykitchen
Copy link

binarykitchen commented May 17, 2016

@madvas thanks but one scenario is missing: how to include a custom component as a prop. like this

(ns abc
  (:require [cljsjs.material-ui]                            ; this also loads react (is within)
            [cljs-react-material-ui.core :as mui]
            [cljs-react-material-ui.reagent :as rui]        ; that's the react-material-ui wrapper, not reagent itself!
            [cljs-react-material-ui.icons :as icons]
            [reagent.core :as reagent :refer [atom]]))

;; just an example how to use a full react class instead of the shorter form (because we will need that later!)
(defn user-menu []
  (reagent/create-class
    {:component-did-mount #(println "user-menu-did-mount")
     :display-name        "user-menu"
     :reagent-render      (fn []
                            [rui/icon-menu {:icon-button-element (mui/icon-button {:touch true} (icons/navigation-expand-more))}
                             [rui/menu-item {:primary-text "Edit Profile"}]
                             [rui/menu-item {:primary-text "Logout"}]])}))

(defn user-bar []
  [rui/list
   [rui/list-item {:primary-text "Michael Heuberger" :right-icon-button (user-menu)}]])

Chrome says a warning like

"material-ui.inc.js:2410Warning: Failed propType: Invalid prop rightIconButton supplied to ListItem, expected a single ReactElement. Check the render method of ...."

@madvas
Copy link
Author

madvas commented May 17, 2016

It has to be like this

(defn user-bar []
  [rui/list
   [rui/list-item {:primary-text "Michael Heuberger" :right-icon-button (r/as-element [user-menu])}]])

@madvas
Copy link
Author

madvas commented May 17, 2016

Theoretically u can do the same with rui reagent components, but using it as direct react components is shorter

[rui/app-bar {:title "Title" :icon-element-right
                              (r/as-element [rui/icon-button
                                             (ic/action-account-balance-wallet)])}]

@binarykitchen
Copy link

binarykitchen commented May 17, 2016

cool, thanks. why does it have to be "downcasted" into a react component at all with r/as-element? isnt that too complicated? why can't [rui/app-bar] do this automatically when it receives properties like that?

@binarykitchen
Copy link

also, r/as-element does not produce what i want:

A

(defn user-menu []
  (reagent/create-class
    {:component-did-mount #(println "user-menu-did-mount")
     :display-name        "user-menu"
     :reagent-render      (fn []
                            [rui/icon-menu {:icon-button-element (mui/icon-button {:touch true} (icons/navigation-expand-more))}
                             [rui/menu-item {:primary-text "Edit Profile"}]
                             [rui/menu-item {:primary-text "Logout"}]])}))

(defn user-bar []
  [rui/list
   [rui/list-item {:primary-text "Michael Heuberger" :right-icon-button (reagent/as-element [user-menu])}]])

produces a different HTML than

B

(defn user-bar []
  [rui/list
   [rui/list-item {:primary-text "Michael Heuberger" :right-icon-button (reagent/as-element [rui/icon-menu {:icon-button-element (mui/icon-button {:touch true} (icons/navigation-expand-more))}
                                                                                             [rui/menu-item {:primary-text "Edit Profile"}]
                                                                                             [rui/menu-item {:primary-text "Logout"}]])}]])

in B icon is right, next to text which is correct. in A icon is above text which is wrong.

@madvas
Copy link
Author

madvas commented May 18, 2016

Well, it's because reagent doesn't parse it's syntax in component attributes, only in component body. And material-ui expects there react components, not reagent. Tho it's true I might add this as-element conversion into library for attributes where react component is expected.

The reason for wrong styling is probably, cuz when u use create-class, component-will-mount, etc. that creates another element, which wraps rui/icon-menu, so u might have to play with styling little bit with this user-menu element. Maybe there's other solution, but I don't know now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment