Fork me on GitHub
#reagent
<
2015-11-11
>
mbertheau14:11:53

I want to write a date input component. It parses what the user inputs and when a date can be interpreted, it sets that date in an atom. A date can also be set from the outside (when the page is loaded, to pre-fill the input), in that case the input should be pre-filled with a string representation of the date. Now when the date atom is set after the user entered a valid date, I don't want put the cleanly formatted date in to the input, instead I want to leave it at what the user entered. However when I load something new into the form, I do want the input to contain the cleanly formatted date. How would I distinguish between the two when setting the date atom? My answer is that I need two atoms: one for input and one for output. The component only reads the input atom and never writes it; it only writes the output atom. Is that correct?

mbertheau15:11:00

Hmm, I have one idea, but it's not perfect. I have a second atom that holds the input string value. It's local to the component instance, so it doesn't affect the interface of the component. Now when the date atom changes, I can check whether that's different from what the input string atom is when interpreted as a date, and change the input string only if that is the case. The imperfection is: if I happen to set the atom to the same date that the input string is interpreted as, the input field is left as is, but it should be filled with the cleanly formatted date representation.

erik_price15:11:06

mbertheau: Not everyone subscribes to this idea, but… I never let my Reagent components directly update the atom that they are bound to. They are pretty much read-only. When a Reagent component needs to update some state, it sends an event on an event bus, which is listened to by “controller-level” code in my app. That code is responsible for choosing what value to set in the state atom that the Reagent component updates itself from.

roberto15:11:23

^ I use re-frame to do that. I only use reagent for displaying the state.

mccraigmccraig16:11:19

@erik_price @roberto : i largely subscribe to this idea (via re-frame), but i've ended up with some text inputs with private closed-over atoms they use to hold their value, which they update directly... and then dispatch an event to update global state - otherwise i got event-loop race conditions with even moderate typing speed

erik_price16:11:04

eh, some local state isn’t always a bad thing

roberto16:11:35

yeah, also, has anyone implemented debounce with reagent?

mbertheau16:11:14

@erik_price: I use re-frame for that, just didn't want to go into that detail, since it's irrelevant for my question simple_smile

erik_price16:11:01

well, in my app, I’d have just one atom holding the date text. When the user enters some input, I’d set the atom to the text the user entered, and apply the rule of not formatting it cleanly. And when the system loads some input, I’d set the atom to the text from wherever the system gets it, and apply the formatting. All of that logic would live in the controller layer – the component would remain “dumb” and just display whatever the current state of the atom is.

mbertheau16:11:54

@erik_price: What do you do when the input cannot be interpreted as a date? Let's assume you leave the value as is. Then when the input is such that it can be interpreted as a date, you reset the input's value to the text representation of that date while the user is typing?

mbertheau16:11:53

@erik_price: Ah, now I understand.

erik_price16:11:41

🙇:skin-tone-3:

mbertheau16:11:56

@erik_price: So to put together a date input field you need to arrange a number of pieces correctly, instead of just using one component. Hmm! simple_smile

erik_price16:11:57

Yes, that’s true. In my app there is a separation between the controllers and the components.

erik_price17:11:26

If I were developing some sort of general-purpose widget toolkit I might try to do things differently, but I’m just trying to keep my app simple.

mbertheau17:11:53

Thanks for your input simple_smile

jstew20:11:56

Anyone successfully using select2 with a reagent component? It seems to swallow the :on-change event.

jstew20:11:03

I'm initializing select2 in :component-did-mount

mitchelkuijpers21:11:15

You might have better luck with the special react select

mitchelkuijpers21:11:46

Select2 has a very weird api

jstew21:11:01

Thanks for that. I'm trying to use a fancy bootstrap theme that's opinionated. Too opinionated for react or cljs though, I think.

mikethompson21:11:17

@mccraigmccraig: version 0.5.0 of re-frame has a "faster" router loop (no longer uses core.async) so that key loss possibility should be a thing of the past.

mikethompson21:11:02

If it isn't, I'd like to hear about it. simple_smile

mccraigmccraig21:11:31

@mikethompson: cool, i'll kick the tires again

mikethompson21:11:36

BTW, in the past, the way to solve this was to use dispatch-sync (generally frowned upon) instead of dispatch. But, like I said, hopefully this is nolonger an issue post v0.5.0