2017-01-16 35 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 "")))))})]))}))) 
相关问题