2015-10-01 3 views
3

Я хочу создать список элементов 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

ответ

4

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

FYI, related discussions.

любая идея, почему второй блок, который я разместил, создает только один элемент?

Векторы являются особыми гражданами для реагента, они рассматриваются как компоненты икоты/реактивов.

Для рабочего примера

(defn like-component [] 
    [:ul 
    (doall 
     (for [ e ["A" "B" "C"]] 
     [expandable-view e true]))]) 

заметить также, что мы используем [expandable-view e true] правильно построить компонент реагента. Для получения дополнительной информации я настоятельно рекомендую прочитать Using [] instead of() и Creating Reagent Components.

+0

Да, снова ланти снова! На самом деле было предупреждение об этом, напечатанном на моей консоли javascript, но я пропустил его между некоторыми уникальными ключевыми ошибками (которые также были легко исправить). Я просто завернул первый пример в 'doall', любую идею, почему второй блок, который я разместил, создает только один элемент? – wovenhead

0

Я достиг такого типа поведения, используя бутстрап. У меня есть список записей в атоме состояния, которые являются всеми хэш-картами. Я добавляю: видимый ключ к каждой карте, который используется для установки соответствующих классов начальной загрузки в записи. Существует функция, которая переключает: видимую настройку на карте. Компонент отображает запись кнопкой, которая переключает видимость, изменяя: видимое значение на карте, заставляя компонент повторно отображать.

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

По существу, позволяя самозагрузки обрабатывать показа/скрытия содержимого, в результате чего код просто переключить видимый/невидимый состояние. Полный код находится на моей странице github в theophilusx/Arcis

Смежные вопросы