2018-06-17 18:20:28 +00:00
|
|
|
# Material-UI
|
|
|
|
|
|
|
|
[Example project](../../examples/material-ui/)
|
|
|
|
|
|
|
|
Material-UI [TextField](https://material-ui.com/api/text-field/) has for long
|
2018-06-17 19:07:57 +00:00
|
|
|
time caused problems for Reagent users. The problem is that `TextField` wraps the
|
2018-06-17 18:20:28 +00:00
|
|
|
`input` element inside a component so that Reagent is not able to enable
|
|
|
|
input cursor fixes, which are required due to [async rendering](http://reagent-project.github.io/news/reagent-is-async.html).
|
|
|
|
|
|
|
|
Good news is that Material-UI v1 has a property that can be used to provide
|
|
|
|
the input component to `TextField`:
|
|
|
|
|
|
|
|
```cljs
|
|
|
|
(ns example.material-ui
|
|
|
|
(:require ["material-ui" :as mui]
|
|
|
|
[reagent.core :as r]))
|
|
|
|
|
|
|
|
(def text-field (r/adapt-react-class mui/TextField))
|
|
|
|
|
|
|
|
(def value (r/atom ""))
|
|
|
|
|
|
|
|
(def input-component
|
|
|
|
(r/reactify-component
|
|
|
|
(fn [props]
|
|
|
|
[:input (-> props
|
|
|
|
(assoc :ref (:inputRef props))
|
|
|
|
(dissoc :inputRef))])))
|
|
|
|
|
|
|
|
(def example []
|
|
|
|
[text-field
|
|
|
|
{:value @value
|
|
|
|
:on-change #(reset! value (.. e -target -value))
|
|
|
|
:InputProps {:inputComponent input-component}}])
|
|
|
|
```
|
|
|
|
|
|
|
|
`reactify-component` can be used to convert Reagent component into React component,
|
|
|
|
which can then be passed into Material-UI. The component should be created once
|
|
|
|
(i.e. on top level) to ensure it is not unnecessarily redefined, causing the
|
|
|
|
component to be re-mounted.
|
|
|
|
For some reason Material-UI uses different name for `ref`, so the `inputRef` property
|
|
|
|
should be renamed by the input component.
|
|
|
|
|
|
|
|
## Wrapping for easy use
|
|
|
|
|
|
|
|
Instead of providing `:InputProps :inputComponent` option to every `TextField`,
|
|
|
|
it is useful to wrap the `TextField` component in a way that the option is added always:
|
|
|
|
|
|
|
|
```cljs
|
|
|
|
(defn text-field [props & children]
|
|
|
|
(let [props (-> props
|
|
|
|
(assoc-in [:InputProps :inputComponent] input-component)
|
|
|
|
rtpl/convert-prop-value)]
|
2018-06-17 18:51:53 +00:00
|
|
|
(apply r/create-element mui/TextField props (map r/as-element children))))
|
2018-06-17 18:20:28 +00:00
|
|
|
```
|
|
|
|
|
2018-08-17 20:51:06 +00:00
|
|
|
Here `r/create-element` and `reagent.impl.template/convert-prop-value` achieve
|
2018-06-17 18:20:28 +00:00
|
|
|
the same as what `adapt-react-class` does, but allows modifying the props.
|
2018-06-17 18:51:53 +00:00
|
|
|
|
|
|
|
**Check the example project for complete code.** Some additional logic is
|
|
|
|
required to ensure option like `:multiline` and `:select` work correctly,
|
|
|
|
as they affect how the `inputComponent` should work.
|
|
|
|
|
|
|
|
TODO: `:multiline` `TextField` without `:rows` (i.e. automatic height) doesn't
|
|
|
|
work, because that requires Material-UI `Input/Textarea`, which doesn't work
|
|
|
|
with Reagent cursor fix.
|