Fork me on GitHub
#hoplon
<
2017-10-27
>
chromalchemy01:10:04

Hoplon.UI provides elem attrs for native js drag events, but does not have a component that sets :draggable "true". So I can't use them. The library has a way of handling elem attributes such that I can't just list arbitrary static attributes to pass to the rendered markup <div myattr="myval"></div> like the native Hoplon way. Is there a way to explicitly pass a static attribute into the HTML markup in a more explicit, late-binding way? Using the the attr param in a defelem, or a do-method? or something like (add-attributes!)?

chromalchemy02:10:21

This fn in the public api looks like it might do what I need. But I don't know how to use it. https://github.com/jumblerg/ui/blob/cbdc3e7980ac59f527fb10c47d847f3d99feb335/lib/src/hoplon/ui/attrs.cljs#L336 @jumblerg Any hints?

chromalchemy02:10:18

Hoplon.UI uses 3 nested divs for a standard component. So I'm not sure if I'm barking up the wrong tree trying to use drag events in a conventional way. (What layer to drag?)

thedavidmeister12:10:06

i've been asked to attempt a rescue for some component in an angular project but i don't know much about angular...

thedavidmeister12:10:28

is there a way to "mount" hoplon into an existing project if i include a compiled js file and give it an id or something?

thedavidmeister12:10:52

the thing that needs fixing would be really really easy to make in hoplon >.<

thedavidmeister13:10:11

@chromalchemy not sure what you're looking at but you can call dom elements as functions and they work like normal hoplon

thedavidmeister13:10:23

(h/div :foo "bar") and ((h/div) :foo "bar") do the same thing

thedavidmeister13:10:27

so i'd expect ((.getElementById js/document "my-div") :myattr "myval") to work, right?

chromalchemy14:10:31

Thanks, I didn't know those patterns.

chromalchemy14:10:24

That works in regular Hoplon. In Hoplon.UI, to create a more consistent and logical box model, things are woven through a series of protocols and such, to create a generic component that consists of 3 nested divs. The middle one i believe is the target for events. But there are no ID's in the generated html, and I can't seem to create any custom attributes in the hoplon.ui components. Stumped about how to target this middle div to simply set a static Dom attribute draggable="true". Here is the middleware where it creates the middle div. https://github.com/jumblerg/ui/blob/cbdc3e7980ac59f527fb10c47d847f3d99feb335/lib/src/hoplon/ui/elems.cljs#L12 And heres where it sets the event listeners on it. https://github.com/jumblerg/ui/blob/cbdc3e7980ac59f527fb10c47d847f3d99feb335/lib/src/hoplon/ui.cljs#L249

alandipert14:10:06

thedavidmeister https://github.com/alandipert/embedded-hoplon-example is an example of "mounting" a hoplon element

thedavidmeister14:10:54

@alandipert sweet thanks i'll check it out 🙂

thedavidmeister14:10:02

good to have options

thedavidmeister14:10:58

@chromalchemy wouldn't the events bubble through all the divs when attached to the dom?

thedavidmeister14:10:25

i haven't used hoplon UI, soz 😕

thedavidmeister14:10:33

i'm surprised that you can't add attributes

thedavidmeister14:10:55

the behaviour i described is just hoplon implementing IFn for all dom elements

chromalchemy14:10:43

Yeah, its really nice when it works, but I feel a bit boxed in not knowing how to modify things like the way Hoplon normally lets you.

thedavidmeister14:10:02

can you use (.-children el) to get at the children of the outer el?

chromalchemy14:10:59

I think the events would bubble properly. But it is missing the draggable= declaration that makes the browser invoke the event.

thedavidmeister14:10:39

if you have the outer el can you do

thedavidmeister14:10:51

((.-firstElementChild el) :draggable "true")

chromalchemy14:10:09

put that in the outer elem?

thedavidmeister14:10:29

(j/with-let [el (make-my-el)] ((.-firstElementChild el) :draggable "true"))

chromalchemy14:10:12

How does (with-let) (make-my-el) fit in in the context of a (defelem)

thedavidmeister14:10:09

(defelem make-my-el ...)

thedavidmeister14:10:47

whatever you're currently doing to make and return an element...

thedavidmeister14:10:08

(j/with-let [el (h/div (h/div))] ((.-firstElementChild el) :draggable "true"))

thedavidmeister14:10:56

hopefully puts draggable="true" on the inner div

chromalchemy15:10:40

@thedavidmeister That works for vanilla Hoplon. But not for UI elems. I get

A sanity hint for incoming uncaught error:
 var el = hoplon.ui.elem.call(null,"hello");
el.firstElementChild. <<< ☢ NULL ☢ <<< call(null,new cljs.core.Keyword(null,"draggable","draggable",1676206163),"true");
for
(defelem demo []
  (j/with-let
    [el (elem "hello")]
    ((.-firstElementChild el) :draggable "true")))
(elem) is the generic component that has the nested divs. I guess there is some magic going on that I just don't know how to amend :thinking_face: I guess I can modify the library directly for this change. Or just go with normal Hoplon. Thanks again for more patterns. I have not used with-let or those js methods yet.

thedavidmeister15:10:56

@chromalchemy hmm, what do you get from (prn (.-outerHTML (elem "hello")))?

thedavidmeister15:10:36

well you don't have a dom element

chromalchemy15:10:18

When i (prn (elem "hello") i get #<Elem: DIV DIV DIV>

thedavidmeister15:10:01

oh, so it's a hoplon.ui.elems/Elem

thedavidmeister15:10:10

not a dom element

thedavidmeister15:10:09

(prn (.-outerHTML (hoplon.ui.elems/-mid (elem "hello"))))

chromalchemy15:10:14

"<div style=\"box-sizing: border-box; display: table-cell; position: relative; pointer-events: auto; border-color: transparent;\"><div style=\"display: block; position: relative; height: 100%; max-height: inherit; cursor: inherit; user-select: none; margin: 0px;\">hello</div></div>"

thedavidmeister15:10:55

(j/with-let [el (elem "hello")] ((hoplon.ui.elems/-mid el) :draggable "true"))

chromalchemy15:10:41

Omg. Yes, that worked! 🎉

thedavidmeister15:10:20

looks like hoplon ui is just wrapping the divs up in that Elem type

thedavidmeister15:10:45

but you can still get them with -out -mid and -in

chromalchemy15:10:57

Nice. I'm mystified by all the protocols and types stuff.

chromalchemy15:10:28

Do i need with-let? What if I just use ((hoplon.ui.elems/-mid (elem "hello")) :draggable "true") somewhere?

thedavidmeister15:10:56

with-let is not magic

thedavidmeister15:10:12

is just shorthand for (let [x ...] ... x)

thedavidmeister15:10:04

so, bind something to x, then do some stuff with x then return x

thedavidmeister15:10:56

(let [el (elem "hello")] ((hoplon.ui.elems/-mid el) :draggable "true") el) would be the same

chromalchemy15:10:28

Got it, shorthand so you can do something with/to the named thing, then return it at the end.

chromalchemy15:10:52

and j/with-let plays nicely with cells I guess.

thedavidmeister15:10:01

definitely works well with cells, especially if you want to add watch functions to a cell

thedavidmeister15:10:33

(j/with-let [c (j/cell ...)] (h/do-watch c ...))

thedavidmeister15:10:39

you can get those hard to reach places that cell= doesn't quite get to

chromalchemy15:10:30

@thedavidmeister Thanks a ton. Was really enlightening.

jjttjj17:10:24

in castra is there a preferred way to communicate to the client the nature of an rpc/pre failure? For example if a spec fails I would like the explain-data sent to client. I've been just been using assertion and merging the ex-data with the spec problems. But this composes weirdly (assertions return nil) and is starting to get kinda weird as I'm adding more and more rules. Is there a better way that I'm missing?

jjttjj17:10:11

is it better to just handle errors in the defrpc body and throw a castra.core/ex?