Clojurians
#hoplon
<
2016-05-17
>

This page is not created by, affiliated with, or supported by Slack Technologies, Inc.

mynomoto04:05:35

@onetom: I'm kind of late but afaik clj-webdriver with taxi api is best for more realistic scenarios with the problem of flakier tests. Use phantom if you can. If kerodon is enough for what you need you should go for it as it's simpler and less flaky imo.

mynomoto04:05:17

@alandipert: I was wondering other day about using hoplon as a library without the hoplon boot task, thanks for https://github.com/alandipert/embedded-hoplon-example

onetom04:05:42

@mynomoto: thanks! do you have a way to deal with the super long and ugly error message of (click "#some.bad.selector")?

alandipert14:05:46

@mynomoto: thanks, glad you like it

jamieorc14:05:00

When creating a static list in hl, do you use loop-tpl or do you prefer for, map, etc?

alandipert14:05:11

i tend to use loop-tpl only when the elements will change

alandipert14:05:19

avoiding the ceremony when i can

jamieorc14:05:49

That was my pref, but just in case I was missing something.

thedavidmeister15:05:37

did we merge if-tpl when-tpl cond-tpl and case-tpl without creating any documentation around tpls in the wiki?

thedavidmeister15:05:57

somehow i missed that

alandipert15:05:20

could probably use more links to it

alandipert15:05:26

feel free to place one wherever you were expecting it :slightly_smiling_face:

thedavidmeister15:05:39

i’m moving things around a bit atm

thedavidmeister16:05:05

i noticed the article titles and intros make perfect sense, but only after you have read them

thedavidmeister16:05:14

like “Attribute multimethods"

thedavidmeister16:05:43

how would someone know that’s how JS events work?

thedavidmeister16:05:48

full marks for accuracy

thedavidmeister16:05:05

but a first-timer would have to re-read that a few times to “get it"

thedavidmeister16:05:02

@alandipert: what you said earlier is the tl;dr of templates i think

thedavidmeister16:05:14

it’s about dynamically rebuilding the DOM as efficiently as possible

thedavidmeister16:05:45

whereas defelem/on!/do! are about setting structure and tweaking attributes

thedavidmeister16:05:22

that there would even need to be a difference between those things did not occur to me until micha spelled it out one day :stuck_out_tongue:

thedavidmeister17:05:15

i gotta crash now

thedavidmeister17:05:21

i’ll work on it some more later

levitanong17:05:41

I’d like to get some feedback on this. This is something I’ve been doing with a project I’m working on, and I’d like to know if this is an antipattern or something. Regardless, I’m putting it here ‘cause it’s possible :grin: https://github.com/hoplon/hoplon/wiki/Cookbook#lenses-with-javelin-rpcs

piotrek18:05:57

Hi, I tried yesterday but had no luck to get an answer :slightly_smiling_face:

piotrek18:05:14

so let me rephrase it in a shorter form

piotrek18:05:40

let’s say I have a cell that get updated outside of my scope

piotrek18:05:30

and I have a few cells that I want to update based on the updated value from the first cell (whenever it changes)

piotrek18:05:44

I am looking for a way to connect those 4 cells so the change in options cell triggers (calculate-result @options results errors loading)

piotrek18:05:08

I was thinking about add-watch but I am wondering if there is a more elegant way to do it

piotrek18:05:20

or maybe I should think about totally different design?

micha19:05:40

@piotrek: i think for asynchronous things you must use a watch

micha19:05:09

formulas don't make sense there because while the async request is in flight the value will be "wrong"

micha19:05:21

formulas are like invariants basically

micha19:05:38

so the dependency graph is critical for guaranteeing correctness

micha19:05:14

formulas sort of unite all the cells in the graph into a single entity that is internally consistent and updates atomically

micha19:05:33

but when your value depends on an async process you can no longer do that

micha19:05:44

so adding a watch is the correct thing to do i think

piotrek19:05:39

@micha: thanks

piotrek19:05:13

I will use add-watch then

jjttjj20:05:17

has there been any attempt in hoplon to make a super magical form generator? starting to work on something now that can take vector of maps describing the fields a form should have and then create all the cells necessary to make it into a "hoplony-form". Something like the form validation demo but a bit more general?

micha20:05:32

we have a thing we use here at adzerk

micha20:05:58

not a form generator really, just powerful specialized custom elements used in combination with a state machine (for managing state with respect to the backend, validation, etc) and using dynamic vars to establish local contexts

micha20:05:29

that is the login screen, as a custom element

micha20:05:37

the index element

micha20:05:58

that does full validation and all that, and knows how to communicate with the backend

micha20:05:03

and handle errors etc

jjttjj20:05:11

@micha awesome thanks just the kind of thing i was looking for

jjttjj20:05:49

i had wanted to remove some repetition from forms for awhile but kept putting it off, but figured i couldn't be the first one to want something like this :simple_smile:

micha20:05:52

all the things in the form/* namespace use dynamic bindings from the form/with-form macro

micha20:05:20

so like the form/text-input element is a text input control

micha20:05:29

basicall a fancy input box

micha20:05:32

it knows which cell to bind itself to by looking at a dynamic var bound by the form/with-field macro, and it knows how to display validation state by looking at the state machine that's bound by the form/with-form macro

micha20:05:50

note how it's nested inside the modal/modal-body element

micha20:05:01

that's why the dynamic vars are useful

micha20:05:24

they establish a context that doesn't need to be passed explicitly down through all elements in the stack

micha20:05:07

also notice how most of the custom elements in there don't need any attributes or other configuration

micha20:05:17

they get all their configuration from the contexts

micha20:05:37

the attributes you see there are overriding the contextual ones for specific cases

micha20:05:52

like :cofus-select on the email address input control

micha20:05:57

that gist is the entire ui for that screen

jjttjj20:05:26

cool i think I'm getting it. so basically the form/ functions all internally use a dynamic *form-machine or field to do all the state swap!ing and such?

micha20:05:10

yeah the form-machine is an object that has properties like :data, :error, etc.

micha20:05:42

and (:foo (:data form-machine)) would be the cell containing the contents of the input control for the :foo field

micha20:05:09

similarly (:foo (:error form-machine)) would be a cell containing validation error message for the :foo field of the form

micha20:05:30

so we bind the form machine instance to form/*form-machine* say

micha20:05:00

so now all the elements that are aware of form machines can configure themselves with the form machine from *form-machine* if there is one

micha20:05:16

but you could override that with the :form-machine attribute on the individual elements if you want to

micha20:05:34

the dynamic vars simply provide default values for attributes of elements

micha20:05:48

so the email address input controil

micha20:05:08

if you submit the form with that field empty you will see it change its state

micha20:05:22

it will turn red and have a message under it like "this field is required" or something

micha20:05:57

the red color is provided by the form/validation-field element

micha20:05:18

that element is designed to work inside a form/with-field context

micha20:05:35

that context binds the *form-field* to :email say

micha20:05:15

so the validation-field element can extract the :email field from the form-machine's errors or whatever

micha20:05:27

so it knows if the entire control should be red or not, for example

micha20:05:37

then inside the validation-field is a text-input

micha20:05:03

that also knows which cell to bind its contents to by looking in the with-field dynamic context

micha20:05:38

and similarly the validation-message element gets its text content from the errors cell of the form machine, using the field bound by with-field

micha20:05:50

i dunno if that is making sense or not lol

micha20:05:00

it seems more complicated in writing than it is

jjttjj21:05:26

@micha: sorry had to run out but that's all extremely helpful, thanks again

micha22:05:26

@jjttjj: here is an example of the form namespace https://gist.github.com/micha/7a734317c1fbf8c93661e38788c44a82

micha22:05:08

one thing to notice there is that you need to make lexical bindings that capture the dynamic vars in the closure

micha22:05:44

we capture the dynamic var's value and make a lexical binding

micha22:05:02

this way we can refer to it in the closure, like if something will happen asynchronously

micha22:05:11

that's like if it happened in another thread basically

micha22:05:29

the dynamic binding wouldn't be there when it is evaluated asynchronously later

micha22:05:46

that's why we close over it lexically with the let binding

jjttjj22:05:05

@micha: woah awesome. gotta run again but definitely going to study/steal that later :simple_smile: