I have some datastructure in an atom I want to bind to inputs using reagent-forms. The tricky thing is, that I want to bind not only the content of the inputs to said atom, but the inputs themselves; i.e. I want to reactively remove and add input fields by manipulating the atom. Here's a simplified example of what I have:
(ns my.app
(:require
[reagent.core :as r]
[reagent-forms.core :as rf]))
(def appstate
(r/atom {1 "a"
2 "b"
3 "c"}))
(defn inputfield
""
[id]
[:input {:field :text
:id [id]}])
(defn inputfields
""
[]
[:div
(for [item @appstate]
(inputfield (first item)))])
(defn total
""
[]
[:div
[rf/bind-fields (inputfields) appstate]
[:div (str @appstate)]])
(r/render
[total]
(js/document.getElementById "mainframe"))
This works insofar as changes to the input fields are reflected by the atom. The shortcoming becomes evident once I evaluate the following:
(swap! appstate #(assoc % 4 "d"))
While this does change the atom, no additional field is created in the DOM. It would seem the reason for this is my following the reagent-forms documentation:
The templates are eagerly evaluated, and you should always call the helper functions as in the example above instead of putting them in a vector. These will be replaced by Reagent components when the bind-fields is called to compile the template.
As far as my understanding of reagent goes, this means that the atom in inputfields
gets dereferenced when bind-fields
is called . The returned components however no longer contain any reference of the atom, hence no re-rendering on atom-change.
Is there any way with reagent forms to get the forms-binding and the reactive creation and deletion of inputs I'm looking for?
Many thanks in advance
Oliver