I want to create a button which, when pressed, adds a new input (or textarea) to the form.
If you want a text field to be added each time the button is clicked, that means that you want the number of displayed text fields to be equal to the number of times the button has been clicked. We can create a signal that tells us how often the button has been clicked by using the countIf id
on the button's clicked
signal¹.
If we have a list of inputs, we can use flow
to display them beneath (or besides) each other. It is fairly straight forward to write a function that takes a number n
and produces a list containing a button and n
text fields.
So now we can just use lift
to hook that function up to our signal that counts the number of button clicks, combine that with the flow
function, and voilà, we have a button that dynamically creates inputs.
(btn, clicked) = Input.button "Click me!"
-- Count how often the clicked signal is true
clicks = countIf id clicked
main = lift2 flow (constant down) $ lift nInputs clicks
nInputs n =
let helper n acc =
if n<=0 then btn : acc
else
-- Input.textField returns a pair containing the field as well as a signal
-- that you can use to access the field's contents. Since I don't actually
-- ever do anything with the contents, I just ignore the signal here.
-- In your real code, you'd probably want to keep the signal around as well.
let (field, _) = Input.textField $ "input " ++ (show n)
in helper (n-1) $ field : acc
in helper n []
¹ Just using count
would count how often the signal changes. Since each click causes the signal's value to change to true and then right back to false, that would count 2 changes per click. By using countIf id
we only count the number of times the signal is true and thus the number of clicks.
As of Elm 0.8, this can indeed be done. See the release announcement, the Input Groups section of the online reference and a code example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With