rum

Simple, decomplected, isomorphic HTML UI library for Clojure and ClojureScript | 0.12.8 https://github.com/tonsky/rum/blob/gh-pages/CHANGELOG.md#0128
misha 2017-07-18T09:08:45.502061Z

@jrychter arity 5(9) component :harold:

jrychter 2017-07-18T09:09:32.519390Z

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

misha 2017-07-18T09:11:50.570840Z

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

jrychter 2017-07-18T09:12:15.580311Z

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

misha 2017-07-18T09:12:26.584555Z

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

misha 2017-07-18T09:13:34.609776Z

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},
 {...}]

jrychter 2017-07-18T09:14:47.636581Z

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.

jrychter 2017-07-18T09:16:00.663678Z

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.

jrychter 2017-07-18T09:17:12.691215Z

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.

misha 2017-07-18T09:18:43.725729Z

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

jrychter 2017-07-18T09:19:12.736217Z

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)

misha 2017-07-18T09:20:11.757873Z

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:

misha 2017-07-18T09:22:26.809316Z

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"

jrychter 2017-07-18T09:23:44.838513Z

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.

jrychter 2017-07-18T09:25:10.870929Z

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.

misha 2017-07-18T09:27:02.913016Z

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

misha 2017-07-18T09:27:44.929011Z

functions are a good idea, yes :troll:

jrychter 2017-07-18T09:29:51.977165Z

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).

misha 2017-07-18T09:30:12.985467Z

... 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.

jrychter 2017-07-18T09:30:39.996148Z

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])}})

misha 2017-07-18T09:31:28.014443Z

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

jrychter 2017-07-18T09:32:33.039529Z

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

misha 2017-07-18T09:35:38.109642Z

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.

misha 2017-07-18T09:37:11.143887Z

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

misha 2017-07-18T09:37:54.159955Z

and may be it is just ok.

jrychter 2017-07-18T09:38:37.175439Z

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).

jrychter 2017-07-18T09:39:55.204379Z

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).