React-Antizer: ClojureScript library for Ant Design React UI components

antizer

Antizer is a ClojureScript library implementing Ant Design React components for Reagent and Rum.

Ant Design is an enterprise-class UI design language and React-based implementation with the following features:

  • An enterprise-class UI design language for web applications.
  • A set of high-quality React components out of the box.
  • Extensive API documentation and examples.

Resources

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.

Who's Using Antizer

Usage

To use Antizer, 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:

  1. 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 being linked to.

  1. 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 provided by https://github.com/dfuenzalida/antizer-demo.

You can also follow the instructions for customization with LESS here.

Quick Example

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)))

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.

Changes

0.3.1

  • Updated antd library to 3.8.0.
  • Added documentation on loading CSS files. #11
  • Added Card.Meta example.
  • Fixed Form example.
  • Minor fomatting changes to docstring.

0.3.0

  • Updated antd library to 3.7.1. #16 thx @sctianwei, @piotr-yuxuan
  • Fixed autocomplete example for empty string.
  • Fixed layout issue in examples.
  • Removed known issue for DatePicker and Calendar components.
  • Added props argument to reagent.create-form. #12 thx @AndreasKlein

0.2.2

  • Updated antd library to 2.12.3.
  • Fixed resource typo in README.md and documentation. #1 thx @weavejester
  • Added missing component: Breadcrumb.Item. #2 thx @weavejester
  • Added new component: Input.TextArea. #3 thx @mbuczko
  • Fixed layout issue in examples.
  • Added note on DatePicker and Calendar known issues.

0.2.1

  • Updated antd library to 2.11.2.
  • Updated instructions for CSS file inclusion.
  • Added Avatar component and example.
  • Fixed layout and CSS styles for examples.
  • Fixed cljsbuild settings for examples.

Known Issues

None

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).

Comments

  • Table scroll
    Table scroll

    Aug 23, 2018

    How is scrolling added to an ant table?

    I tried a few different things and they didn't work. {:scroll {:x "50%"})} {:scroll (clj->js {:x 800})}

    Numbers vs string percentages didn't make a difference.

    Couldn't find any examples.

    Does this even work at the moment?

    Reply
  • Example needed: Form Create inside Modal
    Example needed: Form Create inside Modal

    Aug 28, 2018

    I'm finding it tricky to understand what is necessary to duplicate https://ant.design/components/form/#components-form-demo-form-in-modal using Antizer's create-form approach.

    The tricky part is to find a way to bind the modal OK and Cancel click events so they behave as form buttons and trigger validation correctly. The Ant example accomplishes this using form.refs after using Form.Create to create a modal wrapping a form. It's not clear that Antizer's create-form can handle this wrapped form creation. It's documentation says that form.create 'Calls Form.create() decorator with the form to be created. form can be any hiccup form.'.

    I'd love there to be a Form inside Modal example :)

    I'm using Rum.

    Reply
  • Question regarding adapt-class implementation
    Question regarding adapt-class implementation

    Sep 26, 2018

    I was trying to get the following snippet to work in RUM,

    (def menu-items [{:key "home"
                      :title "Home"
                      :icon "smile"}
                     {:key "about-us"
                      :title "About Us"
                      :icon "smile"}])
    
    (defn menu []
      (ant/menu
       {:theme "dark" :mode "inline" }
       (for [{key :key title :title icon :icon} menu-items]
         (ant/menu-item
          {:key key}
          (ant/icon {:type icon})
          [:span.nav-text title]))))
    

    But, it was not showing up. Digged a bit into the implementation of adapt-class and found this,

    ...
    type# (first children)
    
    new-children (if (sequential? type#)
                           [(sablono.interpreter/interpret children)]
                           children)
    
    vector->react-elems (fn [[key val]]
                                  (if (sequential? val)
                                    [key (sablono.interpreter/interpret val)]
                                    [key val]))
    ...
    

    So, I went ahead changed that to the following and everything started working fine(at least for me 😄 )

    ...
    new-children (sablono.interpreter/interpret children) 
    
    vector->react-elems (fn [[key val]]
                                          [key (sablono.interpreter/interpret val)])
    ...
    

    I think sablono already handles all the cases were input being vector, seq, object etc.. So, this is sufficient for the functionality right?

    Reply
  • How to uncheck a Radio Button?
    How to uncheck a Radio Button?

    Mar 3, 2019

    I could not find a way to uncheck radio buttons? Could you provide some examples?

    [ant/radio
              {:value "today" :checked @checked?} ;; does not re-render if it's false
              "Today"]
    
    Reply
  • Text cursor jumps to last position for ant/input controllable value
    Text cursor jumps to last position for ant/input controllable value

    Mar 4, 2019

    It works fine with html [:input], but for ant/input check this:

    (defn example [_]
      (let [state (r/atom {:title ""})]
        (fn [_]
          [ant/form
           [ant/form-item
            [ant/input
             {:value       (:title @state)
              :on-change   (fn [e] (swap! state assoc :title (.. e -target -value)))
              :placeholder "Title"}]]])))
    Reply
  • Table dataSource not being camel cased automatically
    Table dataSource not being camel cased automatically

    Aug 20, 2019

    If I do something like

    [ant/table {:data-source [..]}
    

    it doesn't work, while [ant/table {:dataSource [...]}] works as expected. Checking the code it looks like it should work really

    (ac/map-keys->camel-case {:data-source "hello"})
    {"dataSource" "hello"}```
    
    Any idea about what could be the issue?
    Reply
  • [BUG] input can not write the Chinese
    [BUG] input can not write the Chinese

    Sep 24, 2019

    (defn abc [] (let [value (r/atom "")] (fn [] [ant/input {:value @value :on-change #(reset! value (-> % .-target .-value))}])))

    Reply
  • Support rum from v0.12.0
    Support rum from v0.12.0

    Jul 3, 2020

    Hello,

    From Rum v0.12.0 release notes

    Breaking ... Replaced Sablono with Daiquiri, reworked Sablono fork (in case if you are depending on Sablono)

    Is antizer going to support the new Rum version? Maybe does some fork which is already support it exist?

    Thanks.

    Reply
  • Update antizer to antd 4.6.1-0
    Update antizer to antd 4.6.1-0

    Oct 11, 2020

    antd version 4.6.1-0 has been merged on cljsjs (https://github.com/cljsjs/packages/pull/2131#event-3840564663)

    Reply
  • How to implement filterDropdown from antd's Table component?
    How to implement filterDropdown from antd's Table component?

    Oct 20, 2020

    Hello!

    I'm trying to recreate antd's Table component that features a filter dropdown function in clojurescript.

    image

    However, looking at the React code, I have no idea how to convert it into clojurescript, more specifically on the part where we deconstruct filterDropdown into setSelectedKeys, selectedKeys, etc.

    The following is the code in React:

    getColumnSearchProps = dataIndex => ({
        filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => (
          <div style={{ padding: 8 }}>
            <Input
              ref={node => {
                this.searchInput = node;
              }}
              placeholder={`Search ${dataIndex}`}
              value={selectedKeys[0]}
              onChange={e => setSelectedKeys(e.target.value ? [e.target.value] : [])}
              onPressEnter={() => this.handleSearch(selectedKeys, confirm, dataIndex)}
              style={{ width: 188, marginBottom: 8, display: 'block' }}
            />
            <Space>
              <Button
                type="primary"
                onClick={() => this.handleSearch(selectedKeys, confirm, dataIndex)}
                icon={<SearchOutlined />}
                size="small"
                style={{ width: 90 }}
              >
                Search
              </Button>
              <Button onClick={() => this.handleReset(clearFilters)} size="small" style={{ width: 90 }}>
                Reset
              </Button>
            </Space>
          </div>
        ),
        filterIcon: filtered => <SearchOutlined style={{ color: filtered ? '#1890ff' : undefined }} />,
        onFilter: (value, record) =>
          record[dataIndex]
            ? record[dataIndex].toString().toLowerCase().includes(value.toLowerCase())
            : '',
        onFilterDropdownVisibleChange: visible => {
          if (visible) {
            setTimeout(() => this.searchInput.select(), 100);
          }
        },
        render: text =>
          this.state.searchedColumn === dataIndex ? (
            <Highlighter
              highlightStyle={{ backgroundColor: '#ffc069', padding: 0 }}
              searchWords={[this.state.searchText]}
              autoEscape
              textToHighlight={text ? text.toString() : ''}
            />
          ) : (
            text
          ),
      });
    

    Can anybody help me? :( Any help or suggestion would be greatly appreciated!

    Reply
  • Update antizer to ant 3.+
    Update antizer to ant 3.+

    Feb 6, 2018

    Ant is already at 3.2.0 with new components, such as List and Divider

    Reply
  • DatePicker has random characters in the position of
    DatePicker has random characters in the position of "Today"

    Sep 12, 2017

    I tried the workaround but still I can't get it to render in english, any ideas?

    Reply
  • How to put html elements inside the antizer elements
    How to put html elements inside the antizer elements

    Jun 9, 2018

    I'm looking to follow: https://ant.design/components/layout/#components-layout-demo-side

    When creating a menu item, if a :span element is included, it fails:

    (a/menu-item {:key 1}
        (a/icon {:type "pie-chart"})
         [:span "Option 1"])
    

    whereas, this is fine:

    (a/menu-item {:key 1}
        (a/icon {:type "pie-chart"})
         "Option 1")
    

    is there a way to include the :span element?

    Reply
  • double icon when use shadow-cljs compile
    double icon when use shadow-cljs compile

    Mar 26, 2019

    example code use shadow-cljs compile,
    image

    Reply
  • Update 3.20.6
    Update 3.20.6

    Aug 2, 2019

                                                                                                                                                                                                           
    Reply
  • Breadcrumb.Item seems to be missing
    Breadcrumb.Item seems to be missing

    Aug 1, 2017

    I expected a breadcrumb-item component to go with the breadcrumb component, but it seems to be missing.

    Reply
  • Bump cljsjs/antd to 3.2.0-0
    Bump cljsjs/antd to 3.2.0-0

    Mar 2, 2018

    Bump cljsjs/antd to 3.2.0-0

    Reply
  • Accessing things like Card.Meta
    Accessing things like Card.Meta

    Jul 25, 2018

    How to translate examples like this from antd docs? See https://ant.design/components/card/

      <Card
        style={{ width: 300 }}
        cover={<img alt="example" src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png" />}
        actions={[<Icon type="setting" />, <Icon type="edit" />, <Icon type="ellipsis" />]}
      >
        <Meta
          avatar={<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />}
          title="Card title"
          description="This is the description"
        />
    
    Reply
  • upgrade antd to 3.12.0
    upgrade antd to 3.12.0

    Jan 9, 2019

    upgrade antd to 3.12.0

    Reply
  • Bump versions, use 3.3.0-0
    Bump versions, use 3.3.0-0

    Apr 9, 2018

                                                                                                                                                                                                           
    Reply