2017-01-16 25 views
2

假設您有一個文本字段,它是使用試劑在cljs中編寫的聊天程序的輸入。它可能看起來像這樣:如何在試劑中定義聊天輸入字段?

(defn chat-input [] 
    (let [written-text (atom "")] 
    (fn [] 
     [:textarea 
     {:value  @written-text 
     :on-change #(reset! written-text (-> % .-target .-value))}]))) 

現在實現發送消息的簡單方法是添加一個發送按鈕。但是有一種互動與聊天非常不可分割,以至於你不可能沒有它:輸入或換入發送消息。但我無法弄清楚如何實現它。

我的第一個嘗試是簡單地添加一個:按鍵按下事件處理程序來發送消息並將狀態重置爲「」。該解決方案受到How to detect enter key press in reagent的啓發。

(defn chat-input [] 
    (let [written-text (atom "")] 
    (fn [] 
     [:textarea 
     {:value  @written-text 
     :on-change #(reset! written-text (-> % .-target .-value)) 
     :on-key-press (fn [e] 
         (let [enter 13] 
          (println "Key press" (.-charCode e)) 
          (if (= (.-charCode e) enter) 
          (reset! written-text "") 
          (println "Not enter."))))}]))) 

的問題是,在:on-key-press調用(reset! written-text "")沒有效果,可能是因爲它是由:on-change事件處理程序覆蓋。

那麼你有關於如何實現這個功能的任何想法?如果是這樣,請分享!

回答

1

你在正確的軌道上,但忘記了js事件模型:在你的情況下,onChangeonKeyPress都被觸發,因爲目標是一個textarea,其中enter鍵改變輸入。因此,首先觸發js onKeyPress,如果密鑰會改變某些內容,則觸發onChange。你需要做的是禁用與preventDefaultkeyPress此默認行爲:

(defn chat-input [] 
    (let [written-text (atom "")] 
    (fn [] 
     [:textarea 
     {:value  @written-text 
     :on-change #(reset! written-text (.. % -target -value)) 
     :on-key-press (fn [e] 
         (when (= (.-charCode e) 13) 
          (.preventDefault e) 
          (reset! written-text "")))}]))) 

應該解決這個問題。

0

這裏有很多更先進的解決方案,對clojurians懶散mccraigmccraig如此仁慈地允許我與你分享。它隨着輸入內容變大而模擬textarea的高度,模擬聊天輸入如何工作。

但這個問題的重要部分是它的:on-key-press包含一個(.preventDefault e)

(defn update-rows 
    [row-count-atom max-rows dom-node value] 
    (let [field-height (.-clientHeight dom-node) 
     content-height (.-scrollHeight dom-node)] 
    (cond 
     (and (not-empty value) 
      (> content-height field-height) 
      (< @row-count-atom max-rows)) 
     (swap! row-count-atom inc) 

     (empty? value) 
     (reset! row-count-atom 1)))) 

(defn expanding-textarea 
    "a textarea which expands up to max-rows as it's content expands" 
    [{:keys [max-rows] :as opts}] 
    (let [dom-node  (atom nil) 
     row-count  (atom 1) 
     written-text (atom "") 
     enter-keycode 13] 
    (reagent/create-class 
    {:display-name "expanding-textarea" 

     :component-did-mount 
     (fn [ref] 
     (reset! dom-node (reagent/dom-node ref)) 
     (update-rows row-count max-rows @dom-node @written-text)) 

     :component-did-update 
     (fn [] 
     (update-rows row-count max-rows @dom-node @written-text)) 

     :reagent-render 
     (fn [{:keys [on-change-fn] :as opts}] 
     (let [opts (dissoc opts :max-rows)] 
      [:textarea 
      (merge opts 
        {:rows  @row-count 
        :value  @written-text 
        :on-change (fn [e] 
            (reset! written-text (-> e .-target .-value))) 
        :on-key-down (fn [e] 
            (let [key-code (.-keyCode e)] 
            (when (and (= enter-keycode key-code) 
               (not (.-shiftKey e)) 
               (not (.-altKey e)) 
               (not (.-ctrlKey e)) 
               (not (.-metaKey e))) 
             (do 
             (.preventDefault e) 
             (send-chat! @written-text) 
             (reset! written-text "")))))})]))}))) 
相關問題