Fork me on GitHub
#reagent
<
2018-04-15
>
reefersleep08:04:14

Maybe I can insert the React-element post-`as-element` somehow, but that probably messes up lifecycle stuff…

pesterhazy10:04:54

as-element works exact like a render fn

pesterhazy10:04:10

I didn’t fully follow your example

pesterhazy10:04:55

What is the-React-element in the snippet?

reefersleep13:04:09

it’s a React element that I get from a parameter in my function

reefersleep13:04:14

let me post a more full example

reefersleep13:04:03

(defcard-rg drag-and-drop
  “Showing an example of drag and drop with beautiful-dnd”
  [DragDropContext {:on-drag-end    (fn [result]
                                      (let [{:keys [source destination]} (-> result
                                                                             (js->clj :keywordize-keys true))
                                            source-index (:index source)
                                            destination-index (:index destination)]
                                        (when destination
                                          (swap! dnd-state merge
                                                 {destination-index (get @dnd-state source-index)
                                                  source-index      (get @dnd-state destination-index)})))) ;;Mandatory
                    :on-drag-update #()           ;; optional
                    :on-drag-start  #()           ;; optional
                    }
   [Droppable {:droppable-id “droppable”
               :direction    “horizontal”}
    (fn droppable-lambda [provided snapshot]
      (let [inner-ref       (.-innerRef provided)
            droppable-props (-> (.-droppableProps provided)
                                (js->clj :keywordize-keys true))
            placeholder     (.-placeholder provided)] ;; need to create placeholder React Element somewhere in order to ensure that a space is kept empty when dragging element away from list
        (reagent.core/as-element
         [:div (merge {:ref   inner-ref
                       :style {:border “1px solid black”
                               :width “100%”
                               :display :flex
                               :justify-content :space-around}}
                      droppable-props)
          (->> @dnd-state
               (map (fn [[idx color]]
                      ^{:key idx}
                      [Draggable {:key          color
                                  :draggable-id color
                                  :index        idx}
                       (fn draggable-lambda [provided snapshot]
                         (let [placeholder     (.-placeholder provided)
                               inner-ref       (.-innerRef provided)
                               draggable-props (-> (.-draggableProps provided)
                                                   (js->clj :keywordize-keys true))
                               draghandle-props (-> (.-dragHandleProps provided)
                                                    (js->clj :keywordize-keys true))
                               provided-draggableprops-style (-> (.. provided -draggableProps -style)
                                                                 (js->clj :keywordize-keys true))]
                           (reagent.core/as-element
                            [:div (merge {:ref inner-ref}
                                         draggable-props
                                         draghandle-props
                                         {:style (merge {:background-color color
                                                         :min-height 30
                                                         :display :flex
                                                         :flex “1 1 auto”}
                                                        provided-draggableprops-style)})
                             “hej”])))])))])))]])

reefersleep13:04:36

Hm, I thought that Slack would ask me to turn it into a snippet. Well, there it is.

reefersleep13:04:39

Specifically, I’m trying to take the placeholder from the provided argument from the droppable-lambda and insert it as the last element of the :div created in that fn.

reefersleep13:04:06

It seems terribly convoluted to me, but it’s how react-beautiful-dnd works

reefersleep13:04:56

Here’s an abbreviated example of what I’m trying to do:

[Droppable {:droppable-id “droppable”
               :direction    “horizontal”}
    (fn droppable-lambda [provided snapshot]
      (let [inner-ref       (.-innerRef provided)
            droppable-props (-> (.-droppableProps provided)
                                (js->clj :keywordize-keys true))
            placeholder     (.-placeholder provided)] ;; need to create placeholder React Element somewhere in order to ensure that a space is kept empty when dragging element away from list
        (reagent.core/as-element
         [:div (merge {:ref   inner-ref}
                      droppable-props)
          ;; ... content ...
          placeholder])))]

reefersleep13:04:40

And I can do it, I mean, no problem - it just doesn’t have the desired effect. Which, I guess, is because of (reagent.core/as-element [:div content React-element]), that is, nesting a React element inside a call to as-element.

reefersleep13:04:03

I tried doing [(reagent.core/adapt-react-class placeholder)] rather than just referencing it directly, but get an error saying that it’s an object, not a string or function, and rightly so. And then, it seems, I’ve run out of reagent converters 🙂

reefersleep13:04:38

(to be accurate - the problem is actually within the [Draggable, not the [Droppable, but the nature of the problem is as described.)

justinlee17:04:30

@reefersleep you do not need to convert if placeholder is already a react element. as-element will convert vectors into react elements and otherwise will just leave the object alone, i believe

justinlee17:04:01

I think something else is wrong

justinlee17:04:20

when you said “it just doesn’t have the desired effect” what happens?

reefersleep17:04:42

@lee.justin.m The desired effect is: dragging an element over others causes them to move out of the way, while the element container keeps the original size - that is, it leaves some space “open” for you to “drop on to”

reefersleep17:04:49

You can see the proper behavior here:

reefersleep17:04:24

What I get instead is that I drag the element - that is, moving it around with the mouse - and other elements move out of the way, but the container for the elements shrinks to original number of elements minus the one I’m dragging, meaning that the shuffling elements are overlapping each other.

reefersleep17:04:57

The placeholder is supposed to solve this somehow.

reefersleep17:04:31

can be run with lein figwheel

justinlee18:04:40

where are you actually rendering the placeholder? I see it being bound in two different places (459 and 474), which seems probably error-prone, but regardless, I’m not sure where its being rendered

reefersleep18:04:18

Nowhere in the current code 😊

reefersleep18:04:37

let me push a change

reefersleep18:04:45

to what I think it should be

reefersleep18:04:34

@lee.justin.m I’ve pushed (amended and pushed with --force-with-lease, did that before I recognized it might cause you trouble)

reefersleep18:04:51

but I guess/hope you can just pull

justinlee18:04:00

so are there really supposed to be two nested droppable-lambdas

reefersleep18:04:17

nope, a droppable with a draggable inside

reefersleep18:04:27

ach, I confused things. Used the placeholder on the droppable level, not the draggable.

reefersleep18:04:30

just pushed again

justinlee18:04:33

right. are you supposed to be rendering the placeholder from droppable or draggable

reefersleep18:04:36

but the result remains the same

reefersleep18:04:06

well, from what I can tell in the docs, both.. but it’s always nil for the droppable, whereas it takes a value for the draggable when I’m dragging

justinlee18:04:51

in this example, they render the placeholder from the droppable https://codesandbox.io/s/mmrp44okvj

reefersleep18:04:58

The interesting thing is that if I do

(if placeholder 
   placeholder 
   [:div ...(more content here)])
inside the draggable-lambda, I get the space-occupying behavior, but the item I’m dragging becomes invisible

reefersleep18:04:12

which makes sense, I guess.

reefersleep18:04:42

yes, I went by that example as well

reefersleep18:04:34

but it does no good - the placeholder on the droppable level is always nil

justinlee18:04:42

okay so one potential issue: in the example i looked at, the placeholder is a sibling to the mapped sequence. in your example, you are rendering a placeholder inside each draggable

reefersleep18:04:28

yes, this should be different on the draggable and droppable level according to the docs.

justinlee18:04:28

if you look at my example, it’s basically [Droppable [:div (sequence) placeholder]]

justinlee18:04:29

basically i think your issue is with the library, not with reagent interop. you should be able to plunk a react element down inside a reagent vector and it should render

reefersleep18:04:30

I’ve tried both approaches for both levels, in combination. It seems I’ve confused things with the docs - they say it’s the other way around 🙂

justinlee18:04:37

these libraries are hard to get right. i’ve used react-dnd and it was a terror, even in straight javascript

justinlee18:04:54

I’d probably try to transcribe a working example first

reefersleep18:04:20

the draggable placeholder should be a sibling to the node, the droppable should be inside the node

reefersleep18:04:36

It’s good to hear that I’m not the only one to be confused at least 😄

reefersleep18:04:41

and thanks a lot for your time!

justinlee18:04:55

well maybe the issue is that you are only rendering one of them? maybe you should do both?

justinlee18:04:12

yea good luck. i can’t help so much with the substance of the library because I’m not familliar with it

reefersleep18:04:10

I should think I’ve tried both at once, but maybe I should be more meticulous in my approach 🙂

reefersleep18:04:12

ach, you can’t make something a “sibling” to a node in a cljs function - it will return the last evaluated val, that is to say, the “last sibling”

justinlee18:04:19

it would be really nice if there was a tool to log these parameters to the console in a meaningful way

justinlee18:04:39

you’ll need to use into

justinlee18:04:44

its kind of annoying

justinlee18:04:47

but not too bad

reefersleep18:04:16

but into what, exactly?

justinlee18:04:23

the containing div

reefersleep18:04:41

ah, but that’s the thing, right - I want it to be a sibling to the div

reefersleep18:04:59

there’s no containing element

reefersleep18:04:01

that I can tell

reefersleep18:04:09

(which I don’t understand)

reefersleep18:04:59

ah wait, I see now, the placeholder is in the droppable div.

justinlee18:04:10

the div on 461. it’s just a vector, where the first element is :div, the second element is the merged props, the third is the sequence, and the fourth is the placeholder

reefersleep18:04:51

yeah, sure, I’ve done that a ton of times

reefersleep18:04:07

no difference. But I’ll try some more combinations more meticulously

reefersleep19:04:15

(I’ve got the code the way you describe it, with the placeholder being the fourth element of the droppable div, and things are still not acting properly)

justinlee19:04:56

any possibility that “hej” is messing things up?

reefersleep19:04:40

I wonder if the messiness of it all is inherent to the complexity of this level of abstraction of drag-and-drop, or if it is incidental… or incidental to JS code… or incidental to JS React code 🙂

reefersleep19:04:44

I can try removing it

reefersleep19:04:17

no difference

justinlee19:04:30

the library itself is very complex with these nested render funcs

justinlee19:04:59

the js is hard to read, imo

reefersleep19:04:25

someone at work suggested I make a port to cljs instead… I’m kind of daunted by that challenge, but wish that someone would have done so 😄 I find the JS hard, too

justinlee19:04:59

um yea better to slog through the interop. dnd is just hard

reefersleep19:04:19

also, they pull in other deps, I think. And not trivial ones.

justinlee19:04:52

you’re going to want to what I did: I started a fresh new project and then step by step ported over the simple examples with as few diversions as possible, then carefully turned that into something i could use

justinlee19:04:15

you want your code to look exactly like a working example

reefersleep19:04:44

Cheers 🙂 This is pretty much what I did, but I can give it another go.

justinlee19:04:16

what code did you work off of?

reefersleep19:04:42

the example you posted 😄

reefersleep19:04:52

and docs and other examples

reefersleep19:04:36

But that one is very simple and close to what I want (it’s just the content of the containers that I want to be something a bit more complex, but that shouldn’t really make a difference)

reefersleep19:04:52

because the complexity is contained.

reefersleep19:04:56

nothing to do with the dnd

justinlee19:04:58

hm well i’m headed out but i might have some time to take a look later this evening

reefersleep19:04:24

dude, thanks a bunch. I’m hoping to write up an example of this stuff if I manage to get it working, I think it’s sorely missing 🙂

justinlee19:04:54

i put together the interop guide and i’ve been thinking a more complex example with render funcs would be handy

justinlee19:04:08

this is a good example of flavor-of-the-month react library interop

reefersleep19:04:25

:thumbsup: 😄

reefersleep19:04:06

Plus, it’d just be neat for people to use this particular lib. It’s too bad if cljs-using peeps are cut off from useful JS libs