Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions example/test-app/src/example/reactive_fragment.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,32 @@
;; Idea: write some unit tests for the for-fragment macro
,))))

(defn dynamic-fragment-crash-test []
($ :article
($ :h2 "Dynamic fragments composition (crash test)")
(vw/for-fragment* (range 2)
(fn [index1]
(vw/for-fragment* (range 2)
(fn [index2]
(let [just-started (sr/create-state true)
is-even (sr/create-state true)]
(vw/if-fragment just-started
($ :div ($ :button {:on/click #(reset! just-started false)} "Start"))
(vw/if-fragment is-even
($ :div
(str index1 " " index2 " ")
"The value is even."
($ :button {:on/click #(reset! is-even false)} "Make it odd."))
($ :div
(str index1 " " index2 " ")
"The value is odd."
($ :button {:on/click #(reset! is-even true)} "Make it even.")))))))))))

(defn reactive-fragment-root []
($ :div
($ if-fragment-article)
($ case-fragment-article)
($ cond-fragment-article)
($ for-fragment-article)
($ dynamic-fragment-crash-test)
,))
26 changes: 19 additions & 7 deletions src/vrac/web.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -248,11 +248,27 @@

(reset! old-props props)))))))

#?(:cljs
(defn- collect-dom-nodes! [^js/Array array x]
(cond
(instance? js/Node x)
(.push array x)

(vector? x)
(doseq [item x]
(collect-dom-nodes! array item))

(reactive-fragment? x)
(doseq [item @(:reactive-node x)]
(collect-dom-nodes! array item)))))


#?(:cljs
(defn dynamic-children-effect
"Dynamically update the DOM node so that its children keep representing the elements array.
The elements are either js/Element or a reactive node whose value is a sequence of js/Element."
[^js/Element parent-element elements]
The elements are either js/Node (element or text node) or a reactive node whose value is
a vector of js/Node instances."
[^js/Element parent-element nodes]
;; TODO: This algorithm could be improved to only replace children where it is needed.
;; Would it be faster? less CPU-intensive?
;; maybe different algorithms depending on the size?
Expand All @@ -263,11 +279,7 @@
(binding [*xmlns-kw* xmlns-kw
*userland-context* userland-context]
(let [new-children (make-array 0)]
(doseq [element elements]
(if (reactive-fragment? element)
(doseq [sub-element @(:reactive-node element)]
(.push new-children sub-element))
(.push new-children element)))
(collect-dom-nodes! new-children nodes)
(-> parent-element .-replaceChildren (.apply parent-element new-children)))))))))

;; ----------------------------------------------
Expand Down