This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-04-15
Channels
- # beginners (34)
- # boot (6)
- # cider (20)
- # cljs-dev (5)
- # clojure (7)
- # clojure-austin (1)
- # clojure-dusseldorf (10)
- # clojure-spec (11)
- # clojure-uk (3)
- # clojurescript (7)
- # cursive (1)
- # datomic (6)
- # defnpodcast (1)
- # hoplon (2)
- # luminus (32)
- # lumo (9)
- # nrepl (2)
- # nyc (1)
- # off-topic (18)
- # onyx (9)
- # portkey (3)
- # re-frame (27)
- # reagent (102)
- # shadow-cljs (70)
- # tools-deps (25)
- # vim (2)
Maybe I can insert the React-element post-`as-element` somehow, but that probably messes up lifecycle stuff…
as-element works exact like a render fn
I didn’t fully follow your example
What is the-React-element in the snippet?
it’s a React element that I get from a parameter in my function
let me post a more full example
(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”])))])))])))]])
Hm, I thought that Slack would ask me to turn it into a snippet. Well, there it is.
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.
It seems terribly convoluted to me, but it’s how react-beautiful-dnd works
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])))]
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
.
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 🙂
(to be accurate - the problem is actually within the [Draggable
, not the [Droppable
, but the nature of the problem is as described.)
@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
@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”
You can see the proper behavior here:
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.
The placeholder
is supposed to solve this somehow.
The code is here; https://github.com/Reefersleep/cards-for-fast-cities
can be run with lein figwheel
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
Nowhere in the current code 😊
let me push a change
to what I think it should be
@lee.justin.m I’ve pushed (amended and pushed with --force-with-lease, did that before I recognized it might cause you trouble)
but I guess/hope you can just pull
nope, a droppable with a draggable inside
ach, I confused things. Used the placeholder
on the droppable level, not the draggable.
just pushed again
right. are you supposed to be rendering the placeholder
from droppable or draggable
but the result remains the same
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
in this example, they render the placeholder from the droppable https://codesandbox.io/s/mmrp44okvj
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 invisiblewhich makes sense, I guess.
yes, I went by that example as well
but it does no good - the placeholder
on the droppable
level is always nil
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
yes, this should be different on the draggable
and droppable
level according to the docs.
if you look at my example, it’s basically [Droppable [:div (sequence) placeholder]]
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
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 🙂
these libraries are hard to get right. i’ve used react-dnd and it was a terror, even in straight javascript
the draggable
placeholder should be a sibling to the node, the droppable
should be inside the node
It’s good to hear that I’m not the only one to be confused at least 😄
and thanks a lot for your time!
well maybe the issue is that you are only rendering one of them? maybe you should do both?
yea good luck. i can’t help so much with the substance of the library because I’m not familliar with it
I should think I’ve tried both at once, but maybe I should be more meticulous in my approach 🙂
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”
it would be really nice if there was a tool to log these parameters to the console in a meaningful way
but into what, exactly?
ah, but that’s the thing, right - I want it to be a sibling to the div
there’s no containing element
that I can tell
(which I don’t understand)
ah wait, I see now, the placeholder is in the droppable div.
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
yeah, sure, I’ve done that a ton of times
no difference. But I’ll try some more combinations more meticulously
(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)
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 🙂
I can try removing it
no difference
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
also, they pull in other deps, I think. And not trivial ones.
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
Cheers 🙂 This is pretty much what I did, but I can give it another go.
the example you posted 😄
and docs and other examples
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)
because the complexity is contained.
nothing to do with the dnd
hm well i’m headed out but i might have some time to take a look later this evening
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 🙂
i put together the interop guide and i’ve been thinking a more complex example with render funcs would be handy
:thumbsup: 😄
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