試薬用のフォームデータバインディングを提供するためのClojureScriptライブラリは、ライブデモについてはこちらをご覧ください。
ライブラリは、試薬原子をドキュメントストアとして使用します。コンポーネントは:field属性を使用してドキュメントにバインドされています。このキーは、特定のタイプのコンポーネントをどのようにバインドするかを決定するために使用されます。コンポーネントは、ドキュメントと相関するために使用される一意:id属性も提供する必要があります。ライブラリはTwitter Bootstrapでの使用に向けられていますが、作成するコンポーネントの種類についてはかなり不可知論的です。
:id 、例: {:id :foo} 、または{:foo {:bar "value"}}にマッピングされるキーワード化されたパス{:id :foo.bar}にすることができます。または、ベクトルパスを明示的に指定することもできます[:foo 0 :bar] 。
デフォルトでは、コンポーネント値はドキュメントフィールドの値ですが、すべてのコンポーネントは:in-fnおよび:out-fn関数属性をサポートしています。 :in-fn現在のドキュメント値を受け入れ、コンポーネントに表示されるものを返します。 :out-fnコンポーネント値を受け入れ、ドキュメントに保存するものを返します。
次の種類のフィールドが箱から出してサポートされています。
入力フィールドには、次のタイプを作成できます:text 、 :numeric 、 :range 、 :password 、 :email 、および:textarea 。入力は、通常のHTML入力と同じように動作し、 :on-changeのようにドキュメント状態を更新します。
[ :input.form-control { :field :text :id :first-name }]
[ :input.form-control { :field :numeric :id :age }]入力フィールドには、値にフォーマット文字列を提供できるオプション:fmt属性を持つことができます。
[ :input.form-control
{ :field :numeric :fmt " %.2f " :id :bmi :disabled true }]数値入力は、HTML 5の入力の属性をサポートしています:
[ :input
{ :field :numeric
:id :volume
:fmt " %.2f "
:step " 0.1 "
:min 0
:max 10 }] TypeaHeadフィールドは、A :data-sourceキーを使用して、現在の入力を取得し、一致する結果のリストを返す関数にバインドされています。コントロールは、入力要素を使用してユーザーの入力を処理し、1つ以上のリストアイテム要素を含む順序付けられていないリスト要素として選択のリストをレンダリングします。ユーザーは、キーを使用してこれらの各要素をレンダリングするために使用されるCSSクラスを指定できます:入力クラス、:リストクラス、および:アイテムクラス。ユーザーはさらに、CSSクラスを指定して、現在の選択のハイライトを次のように処理できます。ハイライトクラスキー。リファレンスCSSクラスは、リソース/パブリック/CSS/Reagent-Forms.CSSファイルに含まれています。
( defn friend-source [text]
( filter
#( -> % ( .toLowerCase %) ( .indexOf text) ( > -1 ))
[ " Alice " " Alan " " Bob " " Beth " " Jim " " Jane " " Kim " " Rob " " Zoe " ]))
[ :div { :field :typeahead
:id :ta
:input-placeholder " pick a friend "
:data-source friend-source
:input-class " form-control "
:list-class " typeahead-list "
:item-class " typeahead-item "
:highlight-class " highlighted " }]TypeaHeadフィールドは、マウスとキーボードの両方の選択をサポートしています。
入力の表示値をドキュメントに保存されている値とは異なるようにすることができます。指定する必要があります:out-fn 、a :result-fnおよびoptional :in-fn 。 :data-sourceベクトル[display-value stored-value]を返す必要があります。
( defn people-source [people]
( fn [text]
( ->> people
( filter #( -> ( :name %)
( .toLowerCase )
( .indexOf text)
( > -1 )))
( mapv #( vector ( :name %) ( :num %))))))
[ :div { :field :typeahead
:data-source ( people-source people)
:in-fn ( fn [num]
[( :name ( first ( filter #( = num ( :num %)) people))) num])
:out-fn ( fn [[name num]] num)
:result-fn ( fn [[name num]] name)
:id :author.num }]]]場合:data-sourceキーワードに合格したときに完全なオプションリストで応答します:all矢印キーにリストが表示されます。
:selections属性は、選択を保持するために使用される原子を渡すように指定できます。これにより、TypeaHeadテキストを使用してリストを取得するオプションが得られます。AJAX応答ハンドラーが原子を設定した場合、リストがポップダウンします。
供給された場合、 :get-index関数は、リストがポップダウンしたときに選択されたアイテムが強調表示されるようにします。
完全な例は、デモンストレーションページのソースコードで利用できます。
チェックボックスフィールドは、チェックボックス要素を作成します。
[ :div.row
[ :div.col-md-2 " does data binding make you happy? " ]
[ :div.col-md-5
[ :input.form-control { :field :checkbox :id :happy-bindings }]]]チェックボックスには、オプション:checked属性を受け入れます。設定すると、チェックボックスが選択され、以下のドキュメントパスが次のとおりです:idキーはtrueに設定されます。
[ :div.row
[ :div.col-md-2 " does data binding make you happy? " ]
[ :div.col-md-5
[ :input.form-control { :field :checkbox :id :happy-bindings :checked true }]]]範囲制御は次のことを使用します:minおよび:maxキーはHTML範囲入力を作成します。
[ :input.form-control
{ :field :range :min 10 :max 100 :id :some-range }]ラジオボタンは以下を使用しません:idキーは一意であり、代わりに:name属性を使用してグループ化されている必要があります。 :value属性は、ドキュメントに保存される値を示すために使用されます。
[ :input { :field :radio :value :a :name :radioselection }]
[ :input { :field :radio :value :b :name :radioselection }]
[ :input { :field :radio :value :c :name :radioselection }]ラジオボタンはオプションを受け入れます:checked属性。設定すると、チェックボックスが選択され、 :nameキーによって指定されたドキュメントパスがtrueに設定されます。
[ :input { :field :radio :value :a :name :radioselection }]
[ :input { :field :radio :value :b :name :radioselection :checked true }]
[ :input { :field :radio :value :c :name :radioselection }]ファイルフィールドは<input type="file"/>のFileオブジェクトにバインドします。
[ :input { :field :file :type :file }]ファイルと同じですが、 <input type="file" multiple/>で動作し、 FileListオブジェクト全体にバインドします。
[ :input { :field :files :type :file :multiple true }]リストフィールドには、選択されたときにドキュメントに値が入力されている子要素が含まれています。子要素には、それぞれ、ドキュメントに保存される値を指す:key属性を持っている必要があります。要素の値はキーワードでなければなりません。
要素にはオプションを持つことができます:visible?述語関数を指すキーワード。関数はドキュメントを受け入れ、フィールドを表示するかどうかを示すブール値を返します。
:listフィールドは、 optionの要素を含むHTML select要素を作成するために使用されます。
[ :select.form-control { :field :list :id :many-options }
[ :option { :key :foo } " foo " ]
[ :option { :key :bar } " bar " ]
[ :option { :key :baz } " baz " ]]
( def months
[ " January " " February " " March " " April " " May " " June "
" July " " August " " September " " October " " November " " December " ])
[ :select { :field :list :id :dob.day }
( for [i ( range 1 32 )]
[ :option
{ :key ( keyword ( str i))
:visible? #( let [month ( get-in % [ :dob :month ])]
( cond
( < i 29 ) true
( < i 31 ) ( not= month :February )
( = i 31 ) ( some #{month} [ :January :March :May :July :August :October :December ])
:else false ))}
i])]
[ :select { :field :list :id :dob.month }
( for [month months]
[ :option { :key ( keyword month)} month])]
[ :select { :field :list :id :dob.year }
( for [i ( range 1950 ( inc ( .getFullYear ( js/Date. ))))]
[ :option { :key ( keyword ( str i))} i])]シングル選択フィールドはリストのように動作しますが、さまざまなタイプの要素をサポートし、フィールドを選択解除することを可能にします。
[ :h3 " single-select buttons " ]
[ :div.btn-group { :field :single-select :id :unique-position }
[ :button.btn.btn-default { :key :left } " Left " ]
[ :button.btn.btn-default { :key :middle } " Middle " ]
[ :button.btn.btn-default { :key :right } " Right " ]]
[ :h3 " single-select list " ]
[ :ul.list-group { :field :single-select :id :pick-one }
[ :li.list-group-item { :key :foo } " foo " ]
[ :li.list-group-item { :key :bar } " bar " ]
[ :li.list-group-item { :key :baz } " baz " ]]マルチセレクトフィールドを使用すると、複数の値を選択してドキュメントに設定できます。
[ :h3 " multi-select list " ]
[ :div.btn-group { :field :multi-select :id :position }
[ :button.btn.btn-default { :key :left } " Left " ]
[ :button.btn.btn-default { :key :middle } " Middle " ]
[ :button.btn.btn-default { :key :right } " Right " ]]ラベルは:id属性を使用してドキュメントのキーに関連付けられ、そのキーに値が表示されます。レーブルには、オプションを持つことができます:preambleと:postambleキー。値は:fmtキーに割り当てられたフォーマッタ関数を使用して解釈することもできます。 :placeholderキーは、値がない場合に表示されるテキストを提供するために使用できます。
[ :label { :field :label :id :volume }]
[ :label { :field :label :preamble " the value is: " :id :volume }]
[ :label { :field :label :preamble " the value is: " :postamble " ml " :id :volume }]
[ :label { :field :label :preamble " the value is: " :postamble " ml " :placeholder " N/A " :id :volume }]
[ :label { :field :label :preamble " the value is: " :id :volume :fmt ( fn [v] ( if v ( str v " ml " ) " unknown " )}]アラートは、アラートをトリガーし、オプションの:eventキーを持つことができるフィールドのIDにバインドされています。イベントキーは、ブール値を返す関数を指す必要があります。
オプション:closeable? true/false 、閉じるボタンをレンダリングするかどうかを制御するために提供できます(デフォルトはtrueになります)。
イベントが提供されると、イベントがtrueを返すたびにアラートの本文がレンダリングされます。
[ :input { :field :text :id :first-name }]
[ :div.alert.alert-success { :field :alert :id :last-name :event empty?} " first name is empty! " ]イベントが提供されない場合、IDの値が空でなく、値が表示されるたびにアラートが表示されます。
( def doc ( atom {}))
; ;define an alert that watches the `:errors.first-name` key for errors
[ :div.alert.alert-danger { :field :alert :id :errors.first-name }]
; ;trigger the alert by setting the error key
[ :button.btn.btn-default
{ :on-click
#( if ( empty? ( :first-name @doc))
( swap! doc assoc-in [ :errors :first-name ] " first name is empty! " ))}
" save " ][ :div { :field :datepicker :id :birthday :date-format " yyyy/mm/dd " :inline true }]日付は、次の形式を使用してドキュメントに保存されます。
{ :year 2014 :month 11 :day 24 } DatePickerはオプションを取得することもできます:auto-close? 1日をクリックすると閉じる必要があることを示すための鍵。これはデフォルトでfalseになります。
日付形式は:date-formatキー:
{ :field :datepicker :id :date :date-format " yyyy/mm/dd " } :date-formatフォーマットされた日付を返す関数を指すこともできます。
{ :field :datepicker
:id :date
:date-format ( fn [{ :keys [year month day]}] ( str year " / " month " / " day))}上記は、値を保存するためのカスタム関数を提供できるようにする:save-fnキーと組み合わせて役立ちます。たとえば、JavaScriptの日付オブジェクトを使用したい場合は、次のことを行うことができます。
[ :div.input-group.date.datepicker.clickable
{ :field :datepicker
:id :reminder
:date-format ( fn [date]
( str ( .getDate date) " / "
( inc ( .getMonth date)) " / "
( .getFullYear date)))
:save-fn ( fn [current-date { :keys [year month day]}]
( if current-date
( doto ( js/Date. )
( .setFullYear year)
( .setMonth ( dec month))
( .setDate day)
( .setHours ( .getHours current-date))
( .setMinutes ( .getMinutes current-date)))
( js/Date. year ( dec month) day)))
:auto-close? true }]コンポーネントが塗り直すために更新の新しい日付オブジェクトを返す必要があることに注意してください。
DatePickerはオプションを取ります:lang Keyは、DatePickerのロケールを設定するために使用できます。現在、英語、ロシア語、ドイツ語、フランス語、スペイン語、ポルトガル語、フィンランド語、オランダ語が翻訳に組み込まれています。組み込みの言語を使用するには:langを使用します。
| 言語 | キーワード |
|---|---|
| 英語 | :en-US (デフォルト) |
| ロシア | :ru-RU |
| ドイツ語 | :de-DE |
| フランス語 | :fr-FR |
| スペイン語 | :es-ES |
| ポルトガル語 | :pt-PT |
| フィンランド語 | :fi-FI |
| オランダ語 | :nl-NL |
組み込みの言語ロケールを使用する例:
{ :field :datepicker :id :date :date-format " yyyy/mm/dd " :inline true :lang :ru-RU } DatePickerにカスタムロケールハッシュマップを提供することもできます。 :first-day日曜日から0として始まる週の初日をマークします。すべてのキーを指定する必要があります。
カスタムロケールハッシュマップを使用する例:
{ :field :datepicker :id :date :date-format " yyyy/mm/dd " :inline true :lang
{ :days [ " First " " Second " " Third " " Fourth " " Fifth " " Sixth " " Seventh " ]
:days-short [ " 1st " " 2nd " " 3rd " " 4th " " 5th " " 6th " " 7th " ]
:months [ " Month-one " " Month-two " " Month-three " " Month-four " " Month-five " " Month-six "
" Month-seven " " Month-eight " " Month-nine " " Month-ten " " Month-eleven " " Month-twelve " ]
:months-short [ " M1 " " M2 " " M3 " " M4 " " M5 " " M6 " " M7 " " M8 " " M9 " " M10 " " M11 " " M12 " ]
:first-day 0 }} DatePickerは、正しくレンダリングするために追加のCSSを必要とします。デフォルトのCSSは、リソースパスのreagent-forms.cssで提供されます。ページに含まれていることを確認してください。ファイルは以下を使用して読み取ることができます。
( -> " reagent-forms.css " clojure.java.io/resource slurp)コンテナ要素を使用して、異なる要素をグループ化できます。コンテナを使用して、複数の要素の可視性を設定できます。
[ :div.form-group
{ :field :container
:visible? #( :show-name? %)}
[ :input { :field :text :id :first-name }]
[ :input { :field :text :id :last-name }]]バリデーター関数は、 :validatorを使用してコンポーネントに接続できます。この関数は、ドキュメントの現在の状態を受け入れ、要素に追加されるクラスのコレクションを返します。
[ :input
{ :field :text
:id :person.name.first
:validator ( fn [doc]
( when ( -> doc :person :name :first empty?)
[ " error " ]))}]コンポーネントはオプションを提供する場合があります:visible?決定関数を指す属性のキー。この関数は、ドキュメントの現在の値を取得し、コンポーネントをレンダリングすべきかどうかを決定するために使用される真実の値を生成することが期待されます。
( def form
[ :div
[ :input { :field :text
:id :foo }]
[ :input { :field :text
:visible? ( fn [doc] ( empty? ( :foo doc)))
:id :bar }]]):set-attributesキーは、コンポーネントの属性に関する任意の更新を行う必要がある場合に使用できます。キーは、ドキュメントの現在の値とコンポーネントの属性のマップを受け入れる関数を指す必要があります。関数は、更新された属性マップを返す必要があります。
[ :div
[ :input { :field :text
:id :person.name.first
:validator ( fn [doc]
( when ( = " Bob " ( -> doc :person :name :first ))
[ " error " ]))}]
[ :input { :field :text
:id :person.name.last
:set-attributes ( fn [doc attrs]
( assoc attrs :disabled ( = " Bob " ( -> doc :person :name :first ))))}]]上記の例は、最初の名前の入力の値が「ボブ」の場合に姓入力を無効にします。
フィールドコンポーネントは、他の試薬コンポーネントと同じように動作し、自由に混合できます。以下に完全なフォームの例を参照してください。
フォーム要素は、を使用してネストされた構造に結合できます.パスセパレーターとして。たとえば、次のコンポーネント[:input {:field :text :id :person.first-name}]状態原子の次のパスにバインドします{:person {:first-name <field-value>}}
( defn row [label input]
[ :div.row
[ :div.col-md-2 [ :label label]]
[ :div.col-md-5 input]])
( def form-template
[ :div
( row " first name " [ :input { :field :text :id :first-name }])
( row " last name " [ :input { :field :text :id :last-name }])
( row " age " [ :input { :field :numeric :id :age }])
( row " email " [ :input { :field :email :id :email }])
( row " comments " [ :textarea { :field :textarea :id :comments }])])重要なメモ
テンプレートは熱心に評価されており、ベクトルに入れるのではなく、上記の例のように、常にヘルパー関数を呼び出す必要があります。これらは、テンプレートをコンパイルするためにbind-fieldsが呼び出されると、試薬コンポーネントに置き換えられます。
フォームテンプレートが作成されると、 bind-fields関数を使用してドキュメントにバインドできます。
( ns myform.core
( :require [reagent-forms.core :refer [bind-fields]]
[reagent.core :as r]))
( defn form []
( let [doc ( r/atom {})]
( fn []
[ :div
[ :div.page-header [ :h1 " Reagent Form " ]]
[bind-fields form-template doc]
[ :label ( str @doc)]])))
( reagent/render-component [form] ( .getElementById js/document " container " ))フォームは、人口の多いドキュメントで初期化でき、フィールドはそこにある値で初期化されます。
( def form-template
[ :div
( row " first name "
[ :input.form-control { :field :text :id :first-name }])
( row " last name "
[ :input.form-control { :field :text :id :last-name }])
( row " age "
[ :input.form-control { :field :numeric :id :age }])
( row " email "
[ :input.form-control { :field :email :id :email }])
( row " comments "
[ :textarea.form-control { :field :textarea :id :comments }])])
( defn form []
( let [doc ( atom { :first-name " John " :last-name " Doe " :age 35 })]
( fn []
[ :div
[ :div.page-header [ :h1 " Reagent Form " ]]
[bind-fields form-template doc]
[ :label ( str @doc)]])))bind-fields関数は、オプションのイベントを受け入れます。イベントは、ドキュメントが更新されるたびにトリガーされ、リストされている順序で実行されます。各イベントでは、その前任者によって変更されたドキュメントが表示されます。
イベントは、 id 、 path 、 value 、およびdocumentである3つのパラメーターを取得する必要があります。 id 、フィールドの:id一致し、 pathはドキュメント内のフィールドのパスであり、 valueフォームで変更された値を表し、ドキュメントにはフォームの状態が含まれます。このイベントは、更新されたドキュメントまたはnilを返すことができます。Nil nil返されると、ドキュメントの状態が変更されていません。
以下は:weight :bmiの場合の値を計算するイベントの例です:height
( defn row [label input]
[ :div.row
[ :div.col-md-2 [ :label label]]
[ :div.col-md-5 input]])
( def form-template
[ :div
[ :h3 " BMI Calculator " ]
( row " Height " [ :input { :field :numeric :id :height }])
( row " Weight " [ :input { :field :numeric :id :weight }])
( row " BMI " [ :input { :field :numeric :id :bmi :disabled true }])])
[bind-fields
form-template
doc
( fn [id path value { :keys [weight height] :as doc}]
( when ( and ( some #{id} [ :height :weight ]) weight height)
( assoc-in doc [ :bmi ] ( / weight ( * height height)))))]bind-fieldsにイベント関数のカスタムマップを提供してre-frameなどのライブラリを使用して試薬形式を使用できます。その場合、試薬形式は内部状態を保持せず、あなたが提供する機能は、フィールドの値を取得、保存、更新するために使用されます。これが例です:
( ns foo.bar
( :require [re-frame.core :as re-frame]
[reagent-forms.core :refer [bind-fields]]))
; re-frame events
( re-frame/reg-event-db
:init
( fn [_ _]
{ :doc {}}))
( re-frame/reg-sub
:doc
( fn [db _]
( :doc db)))
( re-frame/reg-sub
:value
:<- [ :doc ]
( fn [doc [_ path]]
( get-in doc path)))
( re-frame/reg-event-db
:set-value
( fn [db [_ path value]]
( assoc-in db ( into [ :doc ] path) value)))
( re-frame/reg-event-db
:update-value
( fn [db [_ f path value]]
( update-in db ( into [ :doc ] path) f value)))
; Functions that will be called by each individual form field with an id and a value
( def events
{ :get ( fn [path] @( re-frame/subscribe [ :value path]))
:save! ( fn [path value] ( re-frame/dispatch [ :set-value path value]))
:update! ( fn [path save-fn value]
; save-fn should accept two arguments: old-value, new-value
( re-frame/dispatch [ :update-value save-fn path value]))
:doc ( fn [] @( re-frame/subscribe [ :doc ]))})
; bind-fields called with a form and a map of custom events
( defn foo
[]
[bind-fields
[ :div
[ :input { :field :text
:id :person.name.first
:valid? ( fn [doc]
( when ( = " Bob " ( -> doc :person :name :first ))
[ " error " ]))}]
[ :input { :field :text
:id :person.name.last }]]
events])要素の可視性は、真実の値として扱われるドキュメントでIDを提供するか、関数を提供することによって設定できます。
( re-frame/reg-event-db
:toggle-foo
( fn [db _]
( update-in db [ :doc :foo ] not)))
( re-frame/reg-sub
:bar-visible?
( fn [db _]
( :bar db)))
( re-frame/reg-event-db
:toggle-bar
( fn [db _]
( update db :bar not)))
( def form
[ :div
[ :input { :field :text
:id :foo-input
:visible? :foo }]
[ :input { :field :text
:id :bar-input
:visible? ( fn [doc] @( re-frame/subscribe [ :bar-visible? ]))}]
( defn page
[]
[ :div
[bind-fields
[ :input { :field :text
:id :foo-input
:visible? :foo-input-visible? }]
event-fns]
[ :button
{ :on-click #( re-frame/dispatch [ :toggle-foo ])}
" toggle foo " ]
[ :button
{ :on-click #( re-frame/dispatch [ :toggle-bar ])}
" toggle bar " ]])再フレームを使用している場合は、再フレームイベントを使用して、フォームのフィールドの再計算をトリガーすることをお勧めします。たとえば、計算されたBMIフィールドを見てみましょう。
( re-frame/reg-sub
:value
:<- [ :doc ]
( fn [doc [_ path]]
( get-in doc path)))
( defn bmi [{ :keys [weight height] :as doc}]
( assoc doc :bmi ( / weight ( * height height))))
( defmulti rule ( fn [_ path _] path))
( defmethod rule [ :height ] [doc path value]
( bmi doc))
( defmethod rule [ :weight ] [doc path value]
( bmi doc))
( defmethod rule :default [doc path value]
doc )
( re-frame/reg-event-db
:set-value
( fn [{ :keys [doc] :as db} [_ path value]]
( -> db
( assoc-in ( into [ :doc ] path) value)
( update :doc rule path value))))
( def events
{ :get ( fn [path] @( re-frame/subscribe [ :value path]))
:save! ( fn [path value] ( re-frame/dispatch [ :set-value path value]))
:doc ( fn [] @( re-frame/subscribe [ :doc ]))})
( defn row [label input]
[ :div
[ :div [ :label label]]
[ :div input]])
( def form-template
[ :div
[ :h3 " BMI Calculator " ]
( row " Height " [ :input { :field :numeric :id :height }])
( row " Weight " [ :input { :field :numeric :id :weight }])
( row " BMI " [ :label { :field :label :id :bmi }])])
( defn home-page []
[ :div
[ :h2 " BMI example " ]
[bind-fields form-template events]]) rule Multimthodは、 :set-value出来事が呼び出されたときにトリガーされ、高さまたは重量が更新されるたびにBMIを計算します。
カスタムフィールドはreagent-forms.core/init-field multimethodを実装することで追加できます。メソッドは2つのパラメーターを使用する必要があります。最初のパラメーターはフィールドコンポーネント、2つ目はオプションです。
デフォルトでは、オプションにはgetとsave! 、そしてupdate!キー。 IDを受け入れ、それに関連付けられたドキュメント値を返す関数のキーポイントget 。 save!関数は、IDとそれに関連する値を受け入れます。 update!関数は、ID、更新を処理する関数、および値を受け入れます。更新を処理する関数は、古い値と新しい値を受け取ります。
フィールド値のカスタムストレージ形式を作成するために、アダプターをフィールドに提供できます。これらは、キーを介してフィールドに渡された一対の関数です:in-fnおよび:out-fn 。 :in-fn :out-fnされたアイテムを変更して、フィールドが保存される前にフィールドの出力を変更します。たとえば、ネイティブjs/Dateオブジェクトをストレージ形式として使用するために、DatePickerを初期化することができます。
[ :div { :field :datepicker :id :birthday :date-format " yyyy/mm/dd " :inline true
:in-fn #( when % { :year ( .getFullYear %) :month ( .getMonth %) :day ( .getDate %)})
:out-fn #( when % ( js/Date ( :year %) ( :month %) ( :day %)))}]アダプターはヌルを渡すことができるため、それらを処理できる必要があります。
iOSのSafariには、次の300ms遅延があります:on-click 、 :touch-eventキーを使用してカスタムトリガーイベントを設定することができます。 Reactで利用可能なイベントのリストについては、こちらをご覧ください。たとえば、使用したい場合は次の:on-click :on-touch-start 。
[ :input.form-control { :field :text :id :first-name :touch-event :on-touch-start }]イベントがiOSで動作するためには、ボタン以外の要素に対するcursor: pointerを設定する必要があることに注意してください。
ReactのTapeventPluginは、反応自体で機能が利用可能になるまで、レスポンシブイベントを作成するための別のオプションです。
このプロジェクトでは、テストを実行するためにDooを使用しています。 DOOサポート環境の1つをインストールする必要があります。詳細については、ドキュメントを参照してください。たとえば、Phantomを使用してテストを実行するには、次を実行します。
lein doo slimer test
Copyright©2018 Dmitri Sotnikov
Eclipse Publicライセンスの下でバージョン1.0または(オプションで)後のバージョンのいずれかで配布されます。