Good morning. A small brainstorm today to review the 4 points I left yesterday.
> 2. getting hiccup vectors from (compute) functions. If yes, them will need to be included as `(html my-hiccup)` We don’t need compute functions to return hiccup vectors which we would include in another component : we already have the components for that.
> 1. passing hiccup vectors in argument of component inclusion.
This also imply that we use a special syntax to include it in the hiccup, to differentiate from printable values (html my-hiccup)
, but it would be more natural to include it in the form [my-hiccup]
… in which case, my-hiccup
is assumed to be a component and not just a piece of hiccup.
This is what the case 4. already covers, so 1. is superseded by 4.
> pre-4. passing a reference to a defc
component in argument to the inclusion of another component.
Yes we should support it, and it should be done in the same way than 4.
> 4. passing some anonymous components `fnc` as argument of component inclusion.
fnc
is totally useful, I want Vrac to have it. Something to keep in mind, it’s that the template inside fnc
can refer to variables from the containing components and use their value.
Example:
(defc item-list [item-comp items]
[:ul (for [item items]
[:li [item-comp item]])])
(defc root-layout []
(let [items (:items global)
bg-color (:bd-color global)
my-anonymous-comp (fnc [item]
[:div {:style {:bg-color bg-color}} (:name item)])]
[item-list my-anonymous-comp items]))
Additionally, we could have a shortcut when fnc
does not take arguments:
(defc strongly-said [message-comp]
[:strong [message-comp]])
(defc root-layout []
(let [greating-message "hello"]
[strongly-said (fnc [] [:div greating-message])]))
;; Using a shortcut, it can be written:
(defc root-layout []
(let [greating-message "hello"]
[strongly-said [:div greating-message]]))
The shortcut feels a lot like the case 1. which was superseded.> 3. passing functions in argument of component inclusion. Maybe it would work as well as passing values, will think about it. It should work in the same way as passing other kind of values, nothing harder to implement here. I wonder how often it would be useful to the users, but it will be supported anyway.
— end of my daily “open brainstorming”, feedback welcome as always.
I am pretty much done with the design and will start implementing stuffs this weekend. If you want to give feedback, now is the right time.
I forgot to talk about the event triggering and the event handling. Basically, the event handling is done in a way very similar to the way Re-frame does. For the event triggering, it looks like that:
(defc my-button [button-id text]
[:button {:on-click (dispatch [:button-clicked button-id])} text])
We don't need a function to wrap the dispatch. The Vrac templates are pure data, if we can understand their meaning when we read them, then the system can too - that's good enough.I forgot yet another bit that I want to throw in the template: local state, for the front end view (no kidding).
It's created like that:
(let [init-val true
show? (local init-val)] ;; this binding is not reactive
(when show? [:div "hello"]))
It's updated via effect handling, like that:
(let [show? (local true)]
[:div {:on-click (dispatch [:switch-show-hide show?])} "X"
(when show? [:div "hello"])])
The effect handler uses the reference to the local state to describe the change, similarly to how it is done on the local db.The effect handler does not need to know where the data is in store .. in fact, nobody needs to know. They would only need to know that it is stored globally, in some anonymous place, and it does not disturb the business logic of the application.
Apparently, I have more documentation work to do on the design. I would like to go back to the data model seen in the template, and how it relates to the data in the local db. Also, I might do the event handling differently than Re-frame after all.
Next brainstorming is tomorrow morning, Taiwan time.
I will try to make an example on what it feels like to build a form in Vrac.