Introduction
Ant Design is an enterprise-class UI design language and React-based implementation. It has the following features:
-
An enterprise-class UI design language for web applications.
-
A set of high-quality React components out of the box.
-
Extensive well-documented API and examples.
Status
All the Ant Design components should be fully functional and production-ready. If you discover any missing or invalid components, please file a ticket.
Install
To use antizer, just add the following to your project.clj
:
[antizer "0.3.1"]
You would also need to add the ClojureScript React library that you will be using.
For Reagent:
[reagent "X.Y.Z"]
For Rum:
[rum "X.Y.Z"]
It is also necessary to include the relevant Ant Design CSS stylesheet in your HTML page. There are two ways that the CSS files can be included:
-
Loading the CSS stylesheet from an external CDN:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/antd/${antd_version}/antd.min.css">
where
${antd_version}
must be the same antd library version as the one that Antizer is using. -
Alternatively, the CSS sheetsheet can be loaded from either of the following classpaths. This can be done via Ring library’s wrap-resource function:
-
cljsjs/antd/development/antd.inc.css
-
cljsjs/antd/production/antd.min.inc.css
An example of how this can be done is illustrated by https://github.com/dfuenzalida/antizer-demo.
-
You can also follow the instructions for customization with LESS here.
Resources
Quick Example
Here’s the classic example to help you get started:
For Reagent:
(require '[antizer.reagent :as ant])
(require '[reagent.core :as r])
(defn click-me []
[ant/button {:on-click #(ant/message-info "Hello Reagent!")} "Click me"])
(defn init! []
(r/render [click-me] (.-body js/document)))
For Rum:
(require '[antizer.rum :as ant])
(require '[rum.core :as rum])
(defn click-me []
(ant/button {:on-click #(ant/message-info "Hello Rum!")} "Click me"))
(defn init! []
(rum/mount (click-me) (.-body js/document)))
Please remember to include the CSS stylesheet using one of the methods specified here, otherwise the components would not be styled correctly. |
It is not recommended to render to the <body> element. This is only done for illustrative purposes. |
Programming Guide
Naming convention
In order to be consistent with ClojureScript naming conventions, all functions and properties are specified in lisp case (aka kebab-case), eg: on-click, wrapper-col
The Ant design components, functions and properties have been translated to kebab-case, via the following rules:
-
Replace all instances of
.
with-
. -
Except for the first letter, insert a dash before any uppercase letters, unless there already is a dash before this letter.
-
Convert the whole string to lowercase.
Ant Design component or function name | Antizer name |
---|---|
Calendar |
calendar |
Checkbox.Group |
checkbox-group |
DatePicker.RangePicker |
date-picker-range-picker |
InputNumber |
input-number |
Modal.confirm |
modal-confirm |
notification.info |
notification-info |
The full list of the Ant Design component and function names can be found here.
Types
As can be seen from the module list here, there are three main types within the Antizer library that maps to the equivalent in the Ant Design library.
-
Functions
-
Properties
-
Components
Functions
These are just normal ClojureScript functions. All the functions reside in their UI respective library namespaces:
Example for reagent:
(require '[antizer.reagent :as ant])
(ant/message-info "Hello World!")
Example for rum:
(require '[antizer.rum :as ant])
(ant/message-info "Hello World!")
The full list of the Ant Design functions can be found here.
Components
These are the backbone of the entire library. Please refer to the Components section of the respective ClojureScript React libraries.
Properties
There is currently only one property type currently: locales
. Please refer to the Localization section of
the respective ClojureScript React libraries.
Return Values
All return values from the callback functions of the Ant Design components and the form functions
will be in the form of JavaScript objects. Please use (js->clj)
to convert them before
any ClojureScript operations are to be performed on them.
Reagent
Components
The Antizer components can be treated like any Reagent components. To use them, wrap them in a Hiccup style list:
(require '[antizer.reagent :as ant])
(defn render-menu []
[ant/menu {:mode "inline" :theme "dark" :style {:height "100%" :width "20%"}
:on-click #(println "You have clicked" %1)}
[ant/menu-item {:key "item1"} "Menu Item 1"]
[ant/menu-item {:key "item2"} "Menu Item 2"]])
All the properties that are passed in can be in kebab-case.
Any properties that begins with |
All return values from the callback functions of the Ant Design components and the form functions
will be in the form of JavaScript objects. Please use |
In some cases, certain components (eg: menu-sub-menu
and tooltip
) can accept React.Elements as their properties. In such cases, please use (reagent.core/as-element)
to turn Reagent’s hiccup forms into React elements.
(require '[antizer.reagent :as ant])
(require '[reagent.core :as r])
(defn render-menu []
[ant/menu {:mode "inline" :theme "dark" :style {:height "100%" :width "20%"}}
;; adds a sub-menu containing a "home" icon and "SubMenu 1" text
[ant/menu-sub-menu {:title
(r/as-element
[:span [ant/icon {:type "home"}] "SubMenu 1"])}]])
The full list of the Ant Design component names can be found here.
Forms
Form creation
Antizer supports the use of Form.create() which helps to collect and validate the form data automatically. If you prefer to do this manually or prefer using another validation library, you can skip the section below and use the the Form API found here.
The following is an example of how to use Antizer’s implementation of Form.create()
:
(require '[antizer.reagent :as ant])
(require '[reagent.core :as r])
(defn actual-form []
(fn [props]
(let [my-form (ant/get-form)]
[ant/form
[ant/form-item {:label "Name"}
(ant/decorate-field my-form "name"
[ant/input])]
[ant/form-item {:label "Password"}
;; validates that the password field is not empty
(ant/decorate-field my-form "password" {:rules [{:required true}]}
[ant/input])]])))
(defn init-form []
(ant/create-form (actual-form)))
(defn init! []
(r/render [init-form] (.-body js/document)))
The initial step involves calling (create-form)
with the form component
to be rendered.
Within the form component the form
object should be obtained
via (get-form)
, which obtains the form
object from the React
component’s property. This should be done only after the component has been constructed.
In the case of Reagent, this can be done right at the start of the
render stage, by wrapping the Reagent Hiccup elements with a function. Next, call
(antizer.reagent.get-form)
to obtain the form object that will be used by the
field decorator and form functions.
It is recommended to pass in the React props to the form render function so that the form object is accessible. This is needed in some cases like nested forms.
Without the wrapper function, (antizer.reagent.get-form) would try to obtain
the form value before the component has been constructed, and thus a nil value
will be returned.
|
Field decoration
(decorate-field)
is used to add automatic data capture and validation features
to each form field. This function accepts the following parameters:
(decorate-field form identifier [options] form-field)
It corresponds to the getFieldDecorator function. For an explaination of the parameters, please refer to the API documentation, the Ant Design Form page and the examples provided.
Form functions
After the form has been obtained via (get-form)
, the form functions can be used.
An example of the usage of these functions is shown here:
(require '[antizer.reagent :as ant])
(require '[reagent.core :as r])
(defn actual-form []
(fn [props]
(let [my-form (ant/get-form)]
[ant/form
[ant/form-item {:label "Name"}
(ant/decorate-field my-form "name" {:rules [{:required true :min 10}]}
[ant/input])]
[ant/form-item
[ant/button {:on-click #(ant/validate-fields my-form)} "Submit"]
[ant/button {:on-click #(ant/reset-fields my-form)} "Reset"]]])))
(defn init-form []
(ant/create-form (actual-form)))
(defn init! []
(r/render [init-form] (.-body js/document)))
The form functions (eg: reset-fields
, validate-fields
) correspond to the form functions which
can be found here.
All return values from the callback functions of the Ant Design components and the form functions
will be in the form of JavaScript objects. Please use |
Localization / i18n
Locale Provider
Antizer supports the use of locale provider to provide localization / i18n support.
This is how it works:
(require '[antizer.reagent :as ant])
(defn render-app []
[ant/locale-provider {:locale (ant/locales "en_US")}
[content]])
It is recommended to place the locale provider at the top level of the application. The whole list of supported locales can be found here.
To add a new language, please refer to this.
Moment.js
Some Ant Design components (eg: calendar
, date-picker
,
date-picker-range-picker
) uses the Moment.js library to display
the dates in the correct language.
To set the locale for Moment.js:
(require '[cljsjs.moment.locale.es])
(defn render-app []
[ant/locale-provider {:locale (ant/locales "es_ES")}
[ant/calendar {:default-value (js/moment)}]])
Note that each locale to be used has to be included using require
seperately.
Rum
Components
The Antizer components can be treated like any other Rum components. This is how to make use of them:
(require '[antizer.rum :as ant])
(defn render-menu []
(ant/menu {:mode "inline" :theme "dark" :style {:height "100%" :width "20%"}
:on-click #(println "You have clicked" %1)}
(ant/menu-item {:key "item1"} "Menu Item 1")
(ant/menu-item {:key "item2"} "Menu Item 2")))
All the properties that are passed in can be in kebab-case.
Any properties that begins with |
All return values from the callback functions of the Ant Design components and the form functions
will be in the form of JavaScript objects. Please use |
In some cases, certain components (eg: menu-sub-menu
and tooltip
) can accept React.Elements as their properties.
In this case, simply send the hiccup form in:
(require '[antizer.rum :as ant])
(defn render-menu []
(ant/menu {:mode "inline" :theme "dark" :style {:height "100%" :width "20%"}}
;; adds a sub-menu containing a "home" icon and "SubMenu 1" text
(ant/menu-sub-menu {:title [:span (ant/icon {:type "home"}) "SubMenu 1"]})))
The full list of the Ant Design component names can be found here.
Forms
Form creation
Antizer supports the use of Form.create() which helps to collect and validate the form data automatically. If you prefer to do this manually or prefer using another validation library, you can skip the section below and use the the Form API found here.
The following is an example of how to use Antizer’s implementation of Form.create()
:
(require '[antizer.rum :as ant])
(require '[rum.core :as rum])
(rum/defcs actual-form
[state]
(let [my-form (ant/get-form state)]
(ant/form
(ant/form-item {:label "Name"}
(ant/decorate-field my-form "name"
(ant/input)))
(ant/form-item {:label "Password"}
(ant/decorate-field my-form "password" {:rules [{:required true}]}
(ant/input))))))
(defn init-form []
(ant/create-form actual-form))
(defn init! []
(rum/mount (init-form) (.-body js/document)))
The initial step involves calling (create-form)
with the form component
to be rendered.
Within the form component the form
object should be obtained
via (get-form)
, which obtains the form
object from the React
component’s property. This should be done only after the component has been constructed.
In the case of Rum, use rum.core/defcs
to define a component that receives the state
parameter. Next, call (antizer.rum/get-form)
with the state
parameter to obtain the
form object that will be used by the field decorator and form functions.
Field decoration
(decorate-field)
is used to add automatic data capture and validation features
to each form field. This function accepts the following parameters:
(decorate-field form identifier [options] form-field)
It corresponds to the getFieldDecorator function. For an explaination of the parameters, please refer to the API documentation, the Ant Design Form page and the examples provided.
Form functions
After the form has been obtained via (get-form)
, the form functions can be used.
An example of the usage of these functions is shown here:
(require '[antizer.rum :as ant])
(require '[rum.core :as rum])
(rum/defcs actual-form
[state]
(let [my-form (ant/get-form state)]
(ant/form
(ant/form-item {:label "Name"}
(ant/decorate-field my-form "name" {:rules [{:required true :min 10}]}
(ant/input)))
(ant/form-item
(ant/button {:on-click #(ant/validate-fields my-form)} "Submit")
(ant/button {:on-click #(ant/reset-fields my-form)} "Reset")))))
(defn init-form []
(ant/create-form actual-form))
(defn init! []
(rum/mount (init-form) (.-body js/document)))
The form functions (eg: reset-fields
, validate-fields
) correspond to the form functions which
can be found here.
All return values from the callback functions of the Ant Design components and the form functions
will be in the form of JavaScript objects. Please use |
Localization / i18n
Locale Provider
Antizer supports the use of locale provider to provide localization / i18n support.
This is how it works:
(require '[antizer.rum :as ant])
(defn render-app []
(ant/locale-provider {:locale (ant/locales "en_US")}
(content)))
It is recommended to place the locale provider at the top level of the application. The whole list of supported locales can be found here.
To add a new language, please refer to this.
Moment.js
Some Ant Design components (eg: calendar
, date-picker
,
date-picker-range-picker
) uses the Moment.js library to display
the dates in the correct language.
To set the locale for Moment.js:
(require '[cljsjs.moment.locale.es])
(require '[antizer.rum :as ant])
(defn render-app []
(ant/locale-provider {:locale (ant/locales "es_ES")}
(ant/calendar {:default-value (js/moment)})))
Note that each locale to be used has to be included using require
seperately.
Examples
To compile the examples:
lein with-profile +examples cljsbuild once
To compile the examples and enable hot reloading with figwheel:
lein with-profile +examples-dev figwheel
After compilation, open up the respective HTML page in the examples/resources
folder in your browser.
Troubleshooting
-
The table or auto complete component is not displaying the data.
Any properties that begins with data
has to be in camel case instead of kebab case, as they will be treated as html attributes. Thus, DO NOT use data-index
and data-source
as they would not work, use dataIndex
and dataSource
instead.
Acknowledgement
Thanks to Ant Design, cljsjs/antd, Reagent, Rum and of course ClojureScript, without which this project would not be possible.
License
Copyright © 2017 Michael Lim
Licensed under Eclipse Public License (see LICENSE).