Well, if you don't like that 'form' you could use a binding.
(binding [form/*state*
{:editing? true
:values form-values
:validation validation-report
:on-change handle-form-change}]
(form/tag
(form/text :name)
(form/number :age)))
Anyways, I would not recommend using the binding but doesn't mean you can't.
I can't quite imagine what your future plans look like but you probably
won't need a macro. ;)
cheers,
/thomas
On Friday, October 2, 2015 at 3:34:48 PM UTC+2, Colin Yates wrote:
>
> Hi Thomas - yes, you are right. The example I provided is all pain/no-gain
> in terms of macros. However, future plans will require manipulating the
> invocation of (for example form/text and form/number) before they are
> evaluated.
>
> Having said all of that, that repeated ‘form’ does bug me a bit :-). I do
> absolutely agree that the cognitive overhead of the macro isn’t justified
> here.
>
> On 2 Oct 2015, at 14:29, Thomas Heller <[email protected] <javascript:>>
> wrote:
>
> Have you tried NOT using a macro at all? This code does not need to be a
> macro at all if you ask me.
>
> Just a little sketch but things could look just about the same without any
> macros at all:
>
> (let [form {:editing? true
> :values form-values
> :validation validation-report
> :on-change handle-form-change}]
> (form/tag form
> (form/text form :name)
> (form/number form :age)))
>
>
> ;; in-ns 'form
>
> (defn text [form field]
> [text-component {:id field
> :value (get-in form [:values field])
> ...}])
>
> (defn tag
> [{:keys [editing?] :as form} & children]
> (into [:div.form.horizontal
> {:class (if editing? "editing" "editable")}]
> children))
>
>
> Use macros very sparingly, most of the time data and functions are just
> better.
>
> Just my 2 cents,
> /thomas
>
> On Wednesday, September 30, 2015 at 10:29:30 PM UTC+2, Colin Yates wrote:
>>
>> Hi all,
>>
>> I am banging my head against the wall - I think it is obvious but I have
>> started too long:
>>
>> The use-case is that I want a form which takes a set of children. The
>> form also takes in some form-wide state, like the form-wide validation, the
>> values for each item etc. I want the macro, for each child, to decorate
>> that child by extracting the validation errors and value from the form-wide
>> state.
>>
>> So, assuming:
>> - validation looks like {:name "Duplicate name" :age "You must be at
>> least 0"}
>> - form-values looks like {:name "a-duplicate-user" :age -1}
>>
>> then my form might look like:
>>
>> (form {:editing? true :values form-values :validation validation-report
>> :on-change handle-form-change}
>> [form/text {:id :name}]
>> [form/number {:id :age}])
>>
>> After the macro I want the following code:
>>
>> [:div.form.horizontal
>> {:class "editing"}
>> [form/text {:id :name :value "a-duplicate-user" :errors "Duplicate
>> name" :on-click (fn [e] (handle-form-change :name (-> e .target .value])]
>> [form/number {:id :age :value "-1" :errors "You must be at least 0"
>> :on-click (fn [e] (handle-form-change :age (-> e .target .value))]]
>>
>> However, ideally the macro would _not_ emit the contents of the input as
>> literals but would emit code that inspects the provided parameters at
>> run-time (i.e. rather than :value "a-duplicate-user" I would much prefer
>> :value (-> state values :name) as that will allow me to pass in an atom for
>> example.
>>
>> I have tried so many variations and evaluating the state (e.g. (:editing?
>> state)) works fine as the emitted code has the destructured values, but
>> that doesn't work for an atom.
>>
>> Here is my attempt at trying to emit code that interrogates the provided
>> parameter.
>>
>> (defmacro form [state & elements]
>> (let [state# state]
>> `[:div.form.horizontal
>> {:class (if (:editing? state#) "editing" "editable")}
>> ~@(map (fn [[_ {:keys [id]} :as child]]
>> (update child 1 assoc
>> :editing? (:editing? state#)
>> :value `(-> (:values state#) 'deref (get ~id))
>> :on-change `(fn [e#]
>> (js/console.log "E: "
>> (cljs.core/clj->js e#))
>> ((:on-change state#) ~id (-> e#
>> .-target .-value)))))
>> elements)]))
>>
>> The error I am getting is that there is such var as the gen-sym's state#
>> in the namespace.
>>
>> The generic thing I am trying to do is remove the boilerplate from each
>> of the items in the form.
>>
>> Any and all suggestions are welcome.
>>
>> Thanks!
>>
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to [email protected] <javascript:>
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> [email protected] <javascript:>
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected] <javascript:>.
> For more options, visit https://groups.google.com/d/optout.
>
>
>
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.