If you think about time and causality to โdisplay the correct viewโ, you do not have a React / Om point. You should not make this decision. You just have to bind the display to one state and make sure that part of the state is correct. As stated in the Chaos Rules, core.async is the way to go.
Since the components of the field are already connected to something external (the collapse all button), I would only model collapsed inside the local state of the form / Then I would provide a collapse-ch channel for the fields so that they could link back when they were clicked. Finally, I would set up an event handler in IWillMount to listen for these clicks:
(def init-state [true true true]) (defn form-view [data owner] (reify om/IInitState (init-state [_] {:collapsed init-state :collapse-ch (chan)}) om/IWillMount (will-mount [_] (let [collapse-ch (om/get-state owner :collapse-ch)] (go (loop [] (let [index (<! collapse-ch)] (om/update-state! owner [:collapsed index] not)) (recur))))) om/IRenderState (render-state [_ {:keys [collapsed collapse-ch]}] (dom/div nil (dom/button #js {:onClick (fn [_] (om/set-state! owner :collapsed init-state))} "Collapse All") (apply dom/div nil (map #(om/build field-view {:collapsed? %1} {:init-state {:index %2 :collapse-ch collapse-ch}}) collapsed (range)))))))
As for the fields, they just need to put their index on the channel with each click:
(defn field-view [data owner] (reify om/IRenderState (render-state [_ {:keys [index collapse-ch]}] (dom/button #js {:onClick (fn [_] (go (>! collapse-ch index)))} (if (:collapsed? data) "Collapsed" "Showing")))))
In case I missed something, a complete example is here . This seems like a lot, but in my experience, this is the best way to achieve a reasonable separation of problems. There is another similar example in tutorial .
source share