试剂中的交互式列表
Interactive list in Reagent
我想创建一个包含 html 个元素(包括查询结果)的列表,这些元素在默认情况下是隐藏的,但用户可以切换该状态。我在下面尝试了几种不同的方法作为玩具示例,但都无法正常工作。
这段代码正确地创建了三个按钮,它们正确地改变了 exps 状态,但从不隐藏内容。
(:require [reagent.core :as r] )
(def exps (r/atom [true true true]))
(defn like-component []
[:div
(for [ [i r] (map-indexed vector ["A" "B" "C"])]
[:div
[:button {:on-click #(swap! exps update-in [i] not)}]
(when (nth @exps i)
[:pre (str i r)])])])
(r/render [like-component]
(js/document.getElementById "app"))
另一方面,下面的代码只会创建一个元素,但它可以正常工作。
(defn expandable-view [e bool]
(let [expanded (r/atom bool)]
(fn []
[:li
[:div.expandable
[:div.header {:on-click #(swap! expanded not)}
"Click me to expand and collapse"]
(if @expanded
[:div.body (allow-html :pre e)])]])))
(defn like-component []
[:ul
(vec
(for [ e ["A" "B" "C"]]
(expandable-view e true ))) ])
(r/render [like-component]
(js/document.getElementById "app"))
编辑:可能相关:
https://github.com/reagent-project/reagent/wiki/Beware-Event-Handlers-Returning-False
for
是惰性的,所以 reagent
不能告诉你在第一个代码片段中取消引用 exps
。
我们可以通过显式取消引用原子来解决它。
(defn like-component []
(apply str @exps) ;; because @exps is a vector, and reagent
;; treat vectors as hiccup component
;; we can't just put `@exps` here.
[:div
(for [ [i r] (map-indexed vector ["A" "B" "C"])]
[:div
[:button {:on-click #(swap! exps update-in [i] not)}]
(when (nth @exps i)
[:pre (str i r)])])])
或者只是将惰性序列包装在 doall
中。
(defn like-component []
[:div
(doall (for [ [i r] (map-indexed vector ["A" "B" "C"])]
[:div
[:button {:on-click #(swap! exps update-in [i] not)}]
(when (nth @exps i)
[:pre (str i r)])]))])
仅供参考,related discussions。
any idea why the second block I posted only creates one element?
向量是试剂的特殊公民,它们被视为 hiccup/React 个组件。
一个工作示例
(defn like-component []
[:ul
(doall
(for [ e ["A" "B" "C"]]
[expandable-view e true]))])
另请注意,我们正在使用 [expandable-view e true]
来正确构建试剂成分。
有关更多信息,我强烈建议阅读 Using [] instead of () and Creating Reagent Components.
我通过使用 bootstrap 实现了这种行为。我在状态原子中有一个记录列表,它们都是哈希映射。我向每个地图添加一个 :visible 键,用于在记录上设置适当的 bootstrap 类。有一个功能可以切换 has 地图中的 :visible 设置。该组件使用一个按钮呈现记录,该按钮通过更改地图中的 :visible 值来切换可见性,从而导致组件重新呈现。
(defn toggle-visibility [k h]
(let [new-v (if (= "show" (:visible h))
"hidden"
"show")]
(state/set-value-in! [(state/this-page) :host-list k :visible] new-v)))
(defn host-component [k]
(let [host (state/value-in [(state/this-page) :host-list k])]
^{:key k} [:div.panel.panel-default
[:div {:class "panel-heading show"}
[:div {:class (condp = (:status host)
"Active" "text-success"
"Inactive" "text-info"
"Unknown" "text-warning"
:else "text-danger")}
[:button {:type "button" :class "btn btn-default"
:aria-label "Expand"
:on-click #(toggle-visibility k host)}
[:span {:class (str "glyphicon "
(if (= "show" (:visible host))
"glyphicon-minus"
"glyphicon-plus"))}]]
[:strong " IPv4 Address: "] (:ipv4 host)
[:strong " Hostname: "] (:hostname host)
[:div.pull-right (str "Host ID: " (:host-id host))]]]
[:div {:class (str "panel-body " (:visible host))}
[:ul.list-group
[:li.list-group-item
[:strong "Host Status: "] (:status host)]
[:li.list-group-item
[:strong "MAC Address: "] (:mac host)]
[:li.list-group-item
[:strong "IPv6 Address: "] (:ipv6 host)]
[:li.list-group-item
[:strong "Operating System: "] (:os host)]
[:li.list-group-item
[:strong "DHCP Client: "] (:dhcp host)
[:strong " DNS Entry: "] (:dns host)
[:strong " Revers DNS Entry: "] (:reverse-dns host)]
[:li.list-group-item
[:strong "Host Type: "] (:host-type host)]
[:li.list-group-item
[:strong "Network Group: "]
(str (:network-group host) " / " (:subgroup-name host))]
[:li.list-group-item
[:strong "Managed By: "] (:management-group host)]
[:li.list-group-item
[:strong "Creation Date: "] (:created-dt host)]
[:li.list-group-item
[:strong "Last Modified Date: "] (:last-modified-dt host)]
[:li.list-group-item
[:strong "Last Seen Date: "] (:last-seen-dt host)]]]]))
本质上,让 bootstrap 处理内容的 showing/hiding,让代码只切换 visible/invisible 状态。完整代码在我的 github 页面 theophilusx/Arcis
我想创建一个包含 html 个元素(包括查询结果)的列表,这些元素在默认情况下是隐藏的,但用户可以切换该状态。我在下面尝试了几种不同的方法作为玩具示例,但都无法正常工作。
这段代码正确地创建了三个按钮,它们正确地改变了 exps 状态,但从不隐藏内容。
(:require [reagent.core :as r] )
(def exps (r/atom [true true true]))
(defn like-component []
[:div
(for [ [i r] (map-indexed vector ["A" "B" "C"])]
[:div
[:button {:on-click #(swap! exps update-in [i] not)}]
(when (nth @exps i)
[:pre (str i r)])])])
(r/render [like-component]
(js/document.getElementById "app"))
另一方面,下面的代码只会创建一个元素,但它可以正常工作。
(defn expandable-view [e bool]
(let [expanded (r/atom bool)]
(fn []
[:li
[:div.expandable
[:div.header {:on-click #(swap! expanded not)}
"Click me to expand and collapse"]
(if @expanded
[:div.body (allow-html :pre e)])]])))
(defn like-component []
[:ul
(vec
(for [ e ["A" "B" "C"]]
(expandable-view e true ))) ])
(r/render [like-component]
(js/document.getElementById "app"))
编辑:可能相关: https://github.com/reagent-project/reagent/wiki/Beware-Event-Handlers-Returning-False
for
是惰性的,所以 reagent
不能告诉你在第一个代码片段中取消引用 exps
。
我们可以通过显式取消引用原子来解决它。
(defn like-component []
(apply str @exps) ;; because @exps is a vector, and reagent
;; treat vectors as hiccup component
;; we can't just put `@exps` here.
[:div
(for [ [i r] (map-indexed vector ["A" "B" "C"])]
[:div
[:button {:on-click #(swap! exps update-in [i] not)}]
(when (nth @exps i)
[:pre (str i r)])])])
或者只是将惰性序列包装在 doall
中。
(defn like-component []
[:div
(doall (for [ [i r] (map-indexed vector ["A" "B" "C"])]
[:div
[:button {:on-click #(swap! exps update-in [i] not)}]
(when (nth @exps i)
[:pre (str i r)])]))])
仅供参考,related discussions。
any idea why the second block I posted only creates one element?
向量是试剂的特殊公民,它们被视为 hiccup/React 个组件。
一个工作示例
(defn like-component []
[:ul
(doall
(for [ e ["A" "B" "C"]]
[expandable-view e true]))])
另请注意,我们正在使用 [expandable-view e true]
来正确构建试剂成分。
有关更多信息,我强烈建议阅读 Using [] instead of () and Creating Reagent Components.
我通过使用 bootstrap 实现了这种行为。我在状态原子中有一个记录列表,它们都是哈希映射。我向每个地图添加一个 :visible 键,用于在记录上设置适当的 bootstrap 类。有一个功能可以切换 has 地图中的 :visible 设置。该组件使用一个按钮呈现记录,该按钮通过更改地图中的 :visible 值来切换可见性,从而导致组件重新呈现。
(defn toggle-visibility [k h]
(let [new-v (if (= "show" (:visible h))
"hidden"
"show")]
(state/set-value-in! [(state/this-page) :host-list k :visible] new-v)))
(defn host-component [k]
(let [host (state/value-in [(state/this-page) :host-list k])]
^{:key k} [:div.panel.panel-default
[:div {:class "panel-heading show"}
[:div {:class (condp = (:status host)
"Active" "text-success"
"Inactive" "text-info"
"Unknown" "text-warning"
:else "text-danger")}
[:button {:type "button" :class "btn btn-default"
:aria-label "Expand"
:on-click #(toggle-visibility k host)}
[:span {:class (str "glyphicon "
(if (= "show" (:visible host))
"glyphicon-minus"
"glyphicon-plus"))}]]
[:strong " IPv4 Address: "] (:ipv4 host)
[:strong " Hostname: "] (:hostname host)
[:div.pull-right (str "Host ID: " (:host-id host))]]]
[:div {:class (str "panel-body " (:visible host))}
[:ul.list-group
[:li.list-group-item
[:strong "Host Status: "] (:status host)]
[:li.list-group-item
[:strong "MAC Address: "] (:mac host)]
[:li.list-group-item
[:strong "IPv6 Address: "] (:ipv6 host)]
[:li.list-group-item
[:strong "Operating System: "] (:os host)]
[:li.list-group-item
[:strong "DHCP Client: "] (:dhcp host)
[:strong " DNS Entry: "] (:dns host)
[:strong " Revers DNS Entry: "] (:reverse-dns host)]
[:li.list-group-item
[:strong "Host Type: "] (:host-type host)]
[:li.list-group-item
[:strong "Network Group: "]
(str (:network-group host) " / " (:subgroup-name host))]
[:li.list-group-item
[:strong "Managed By: "] (:management-group host)]
[:li.list-group-item
[:strong "Creation Date: "] (:created-dt host)]
[:li.list-group-item
[:strong "Last Modified Date: "] (:last-modified-dt host)]
[:li.list-group-item
[:strong "Last Seen Date: "] (:last-seen-dt host)]]]]))
本质上,让 bootstrap 处理内容的 showing/hiding,让代码只切换 visible/invisible 状态。完整代码在我的 github 页面 theophilusx/Arcis