Fork me on GitHub
#rum
<
2017-07-18
>
misha09:07:45

@jrychter arity 5(9) component harold

jrychter09:07:32

@misha 5, plus a number of optional args. Yes… and I think I managed to get it to a bare minimum there. πŸ™‚

misha09:07:50

did you try to group those by field? now those are grouped by "purpose"

jrychter09:07:15

@misha What do you mean? Group which "those"?

misha09:07:26

why is 3rd arg - [[]] instead of {}? what was the corner case there?

misha09:07:34

you have field type in one arg, and validation in another. did you think of declaring those in a single {} for each field? like

[{:data-path [:price]
  :field fields/text
  :validator xforms/pos-int},
 {...}]

jrychter09:07:47

Ordering. If you don't provide a :layout-fn, the form will render your fields and you want them ordered. The arguments are: data (your data, a map), xforms (how to transform your data for display, transform it back, and validate it), fields (ordered mapping of data to field components), metadata (things like labels, choices for selectors, autofocus, etc), and a submit-fn that gets called with your data transformed back after submission.

jrychter09:07:00

Yes, I considered it, and it reduces reuse. As it is, it is very easy to reuse both xforms and form fields, independent of each other. There are many cases where you want that. And I wanted xforms to be composable as well.

jrychter09:07:12

BTW, validation is actually part of the "type" (it's in the xforms), it just isn't tied to a field component. So, a string could use the same xforms (trimming and checking for non-emptiness, for example), but be rendered as either a text field or a search dropdown.

misha09:07:43

(I will need to spend more time on it myself soon, looking for insights)

jrychter09:07:12

Oh, and also β€” same xforms are used both for forms and for tables, which are interested in :display and :sort (you often want to sort on value, but not the displayed value, think dates)

misha09:07:11

here, I am probably suggesting "compiling" form before passing it to component, to be able to inspect it in repl w/o the need of mounted component. I guess, I'm not really sure yet opieop

misha09:07:26

trying to extract as much as possible out of components lately, and bake in as little as possible (like performance critical things and DOM i/o). Still looking for that pragmatic "line"

jrychter09:07:44

In my case, I'm very application-driven. My main focus is writing reusable code that lets me build http://PartsBox.io well, while keeping code small.

jrychter09:07:10

I think whatever you do on the components/interface side, my xforms are fundamentally a very good idea (not mine!). They abstract data transformations to get from an internal (problem domain) representation to a form or display representation, also including validation and form state changes in the process.

misha09:07:02

can you suggest any good read on forms? use cases, corner cases, etc. On one hand it is a rather old problem, on the other hand – everyone is still solving it from scratch. Would love to read a structured decomposed problem definition at least

misha09:07:44

functions are a good idea, yes troll

jrychter09:07:51

Ha, I'd love to, but IMHO there is nothing out there. I wanted to find something myself. I think most approaches are rehashing the problem in same old ways (for example, keeping validation as a separate library). Also, I found that many approaches make assumptions about your language/environment (mostly about client-side language being deficient in some way).

misha09:07:12

... so that anyone would have the same shared vocabulary and list of components pieces to keep in mind, then it would not really matter in which way it is more convenient to assemble those yourself.

jrychter09:07:39

I looked into the code, and here's a bit of doc I wrote about xforms, I think it's good material for thinking about the problem:

;; xforms are transformations that are applied to data so that it can be displayed, prepared for editing, parsed,
;; validated or sorted.
;;
;; There are several kinds of xforms, each stored under a different key:
;;
;;   :display -- transform for display (such as in a table)
;;   :edit -- only necessary if different from :display, transform for editing in a form, by default :display will be used.
;;   :parse -- parse from a form field back into our data (model) representation
;;   :validate -- validate our data (model) representation
;;   :sort -- transform into a form appropriate for sorting. Sorting will use the model representation by default.
;;
;; Two additional xforms are slightly different:
;;
;;   :state -- return one of the allowed field states
;;   :on-change -- when a field changes, return updates to [data metadata]
;;
;; xforms can be combined using (combine), which does a merge, where later xforms override previous ones. Another method
;; is to use function composition, which composes xform functions: the general tools for this are add-xf, add-xf-before
;; and add-xf-after, and add-validator and prepend-validator are specifically designed for composing validators with
;; short-circuiting whenever one fails.
;;
;; xforms function signatures:
(comment
  {:field {:display (fn [{:keys [v] :as data}] v)
           :edit (fn [{:keys [v] :as data}] v)
           :parse (fn [{:keys [v] :as data}] v)
           :validate (fn [{:keys [v] :as data}] true) ; "Or a string with an error message"
           :sort (fn [{:keys [v] :as data}] v)
           :state (fn [{:keys [v] :as data}] v) ; Returns one of the allowed ::forms/+field states+
           :on-change (fn [{:keys [v] :as data}] [data-updates metadata-updates])}})

misha09:07:28

sweet. gtg suddenly, will write back in a few hours

jrychter09:07:33

BTW, thoughts on this are welcome. It is in no way perfect.

misha09:07:38

I have an uneasy feeling, that you can't just solve forms, that forms are always "handmade", as soon as you try to sprinkle tiny bit of usability on them.

misha09:07:11

and handmade form is just 1 step away from managing state inside a component, and so on, until the huge hairy (but potentially performant) ball of code

misha09:07:54

and may be it is just ok.

jrychter09:07:37

I mostly agree. My current work on forms is basically a bunch of compromises. But β€” adding the :state and :on-change xforms goes a long way towards solving most practical use cases, with self-modifying forms (where parts of a form depend on other parts).

jrychter09:07:55

Also, note the peculiar structure: everything is keyed on :field, but functions take the entire data map again, forcing you to extract the field. This is intentional: all too often you want to operate on several fields, not on a single one (most often in validation, but not only, think displaying/editing a value with a currency).