Fork me on GitHub
#clojure-uk
<
2017-11-29
>
thomas08:11:02

moin moin morning

thomas08:11:48

can I just say that I love the conversation from yesterday, so great to see people helping each other and that makes this channel/community such a wonderful place to be! THANK YOU ALL!

practicalli-john08:11:42

I'd like to hear your highlights from the last 10 years of Clojure. This could be language features, projects, first paid job, a talk or tutorial that made a difference to the way you think, something new you did because of Clojure. Its for a presentation to open the ClojureX conference. Either comment here, send me a direct message or email me at john at jr0cket dot eu If you have any pictures from events you would like to share, I can include them too

dominicm08:11:05

Getting a job at JUXT writing Clojure full time was pretty great 🙂

guy08:11:12

Morning!

dominicm08:11:15

@jr0cket what kind of things did you have in mind? I'm struggling to envision it a little.

guy08:11:00

@jr0cket for me its about the community, i found every one so happy and welcoming. Everyone is always so willing to help and share their experiences. I’ve grown to love programming and Clojure through the community.

guy08:11:13

if that makes sense?

practicalli-john08:11:36

@dominicm I think you may be trying to over thinking it. I just want to hear absolutely anything you thought was interesting, fun, mind changing, awesome... A job at JUXT is a great start... Hopefully you all give me so much I can't use it all.. just didn't want this to be just my opinions / bias.

practicalli-john08:11:36

@guy thanks, that's great. Feel free to share any particular examples

practicalli-john08:11:35

I've been finding the https://juxt.pro/blog/posts/clojure-in.html fascinating reads.. so will include some of that too

practicalli-john08:11:00

If there are any interesting blog series or writers / video bloggers you follow, it would be useful to hear about that too... I've found LambdaIsland and PurelyFunctional to be very helpful

guy08:11:54

I think for me it has always been the Clojure dojos and just other developers i’ve worked with. I was always very fond of the Uswitch clojure dojos. Sadly i can’t really make them anymore because of family commitments, but i’m hopeful for next year 😄

Rachel Westmacott09:11:39

@jr0cket in no particular order: feeling like I was learning programming for the first time again, suddenly realising that I didn’t need any of my defensive programming techniques to protect mutable data, discovering the fast feedback of a REPL, discovering the fast visual feedback of Figwheel, getting a job working full time in Clojure, worrying about being a solo developer in Clojure and then finding out how supportive the community is, worrying about hiring a second Clojure developer and then finding out that the group of people who want to write Clojure professionally are (somewhat) self-selecting for pro-activity and intelligence. Oh, and watching Rich Hickey’s Greatest Hits.

maleghast10:11:40

@jr0cket - Meeting Rich and discovering he is as nice as he appears to be. Discovering the sheer joy of Programming again. The Clojure community being the friendliest of All.

thomas10:11:50

@jr0cket I for a long time I thought there was a lack of philosophy in the work I was doing. There was hardly (if ever) a discussion about why we do the things in a certain way we do them and how we do things and how we can become better at what we are doing. Rich Hickey's video introduced this philosophy (for me at least) into programming... that might be the single most important thing for me about clojure and it community.

thomas10:11:50

and also as I am not a particular good developer I need tools that help me make things simple and focus on the actual problem (the business/functional problem) and have to deal (less) with implementation specific details, as they just complect things IMHO.

practicalli-john10:11:06

I find it amazing that we have 33 people getting together this Sunday to hack on Clojure :)

paulspencerwilliams17:11:09

I would have been there if we had a decent rail system in the UK 😉

maleghast11:11:16

@thomas - I know EXACTLY how you feel.

maleghast11:11:40

You just said it better than I could manage before coffee #1 and now you’ve said it, so I don’t have to… 🙂

thomas13:11:00

I bet it is one of those nasty Spring Boot automagical stuff... 😠

Rachel Westmacott13:11:11

I used to hate that.

mccraigmccraig13:11:58

spring... vague memories stirring... i think it seemed like a good idea at the time ?

Rachel Westmacott13:11:20

presumably the actual class is defined in the Spring config somewhere?

thomas14:11:35

dunno.... I kinda moved onto something else for the moment.

maleghast16:11:17

Anyone able to offer quick Reagent help..? I have been Googling for about an hour, but think that I am asking the wrong question. I want to run a function when a select is changed. Clearly I need to attach an onChange to the Select Box, I get that (not that numb), but how do I get the new value of the select in my function?

maleghast16:11:50

Here’s my select:

[:select {:class "order-selector"
                 :name "order-selector"
                 :onChange (fn [e] (select-display-orders e))}
        [:option {:value "all"} "All Orders"]
        [:option {:value "1"} "Low Risk"]
        [:option {:value "0"} "Medium Risk"]
        [:option {:value "-1"} "High Risk"]
        [:option {:value "-2"} "Disrupted"]]]

dominicm16:11:32

(-> e .-target .-value)

maleghast16:11:48

Obviously I am going to do the work in “select-display-orders”

maleghast16:11:40

@dominicm right, so in my function?

dominicm16:11:03

in the callback, yeah

dominicm16:11:34

https://developer.mozilla.org/en-US/docs/Web/Events/change reference for the change event on mdn is very good

dominicm16:11:43

you can click the keys to figure out what they contain

maleghast16:11:04

like this:

(defn select-display-orders
  [eh]
  (let [state @app-state
        orders (get-in state [:client :chains-full client-id 1 :active-orders])
        newvalue (-> eh .-target .-value)]
    ))

dominicm16:11:38

Should be, yep

maleghast17:11:54

And it works, first time! I ❤️ Reagent

mccraigmccraig17:11:50

this bites everyone using react sooner or later @maleghast - file it away for future reference when you can't figure out why all your event fields are nil - https://reactjs.org/docs/events.html#event-pooling

maleghast17:11:53

@mccraigmccraig - Thanks for that, I will indeed.

maleghast17:11:51

Ah, this is if I want the event in an asynchronous manner or to refer back to the event in the future..?

mccraigmccraig17:11:31

e.g. if you want to pass the event to some thing that makes an api call and refers to values from the event later...

maleghast17:11:22

*nods* Yeah, that would be very confusing if one did not have this flagged up in advance. Thanks very much 🙂

maleghast18:11:26

@mccraigmccraig - I wonder if I could trouble you for one more hint re Reagent / React and form-3 components… You remember that you helped me add the markers to the map component that I made?

maleghast18:11:02

I am now updating the list of markers in the app-state r/atom but the markers are not being re-drawn.

maleghast18:11:14

It’s as if the component is not responding to changes in the app-state r/atom

mccraigmccraig18:11:56

can you show me the component code plz

maleghast18:11:07

sure, one sec

maleghast18:11:28

(defn re-leaflet
  [params]
  (let [dn (r/atom nil)
        mapatom (r/atom nil)
        mn (:mapname params)
        lt (:latitude params)
        lg (:longitude params)
        z (:zoom-level params)
        producer-markers (:markers params)]
    (r/create-class
     {:component-did-mount (fn [ref]
                             (reset! dn (r/dom-node ref))
                             (let [map (js/L.map @dn)
                                   mappositioned (-> map (.setView (array lt lg) z))]
                               (.addTo (js/L.tileLayer "http://{s}. mappositioned)
                               (reset! mapatom mappositioned)))
      :component-will-unmount (fn []
                                (r/unmount-component-at-node @dn))
      :display-name (str "Leaflet Map - " mn)
      :reagent-render (fn [params]
                        (when @mapatom
                          (re-leaflet-update-markers mapatom (:markers params))
                          (re-leaflet-add-borders mapatom (keys (:borders params)) (:borders params)))
                        [:div {:style {:height 620}}])})))

maleghast18:11:08

So the “all markers” standard view gets drawn and I see a full payload of markers. When I change the content of that list of markers in the app-state r/atom I can see that the value has been updated in the app-state r/atom, and the map does re-draw, but it doesn’t seem__ to get the different list of markers and just draws them all

maleghast18:11:34

I think I know why… The function that adds the markers to the map does not delete all the markers that are / were already there…

maleghast18:11:43

Not sure how to do that

mccraigmccraig18:11:53

leaflet is stateful - you have to remove markers you no longer want and only need to add new ones

dominicm18:11:09

Don't you need do have ac allback for component-will-update or something too?

mccraigmccraig18:11:19

that means you have to keep references to the markers you create

mccraigmccraig18:11:56

he's doing it in the render fn, which should work ok @dominicm

maleghast18:11:52

Right, here’s the function being called by the component to add the markers:

(defn re-leaflet-update-markers
  [mapatom markers]
  (let [mapinst @mapatom]
    (doall
    (for [marker markers]
      (-> (js/L.marker
          (array
            (:lat marker)
            (:long marker))
          #js {:icon (case (:icon marker)
                   "dark" (js/L.icon (clj->js
                                      {:iconUrl "/public/icon/map_markers/dark.png"
                                       :iconSize [22 37]
                                       :iconAnchor [11 36]
                                       :popupAnchor [0 -26]}))
                   "red" (js/L.icon (clj->js
                                     {:iconUrl "/public/icon/map_markers/red.png"
                                      :iconSize [22 37]
                                      :iconAnchor [11 36]
                                      :popupAnchor [0 -26]}))
                   "orange" (js/L.icon (clj->js
                                        {:iconUrl "/public/icon/map_markers/orange.png"
                                         :iconSize [22 37]
                                         :iconAnchor [11 36]
                                         :popupAnchor [0 -26]}))
                   "green" (js/L.icon (clj->js
                                       {:iconUrl "/public/icon/map_markers/green.png"
                                        :iconSize [22 37]
                                        :iconAnchor [11 36]
                                        :popupAnchor [0 -26]}))
                   (js/L.icon (clj->js
                               {:iconUrl "/public/icon/map_markers/green.png"
                                :iconSize [22 37]
                                :iconAnchor [11 36]
                                :popupAnchor [0 -26]})))})
         (.addTo mapinst)
         (.bindPopup (:name marker)))))
    (reset! mapatom mapinst)))

maleghast18:11:10

So, I need to keep track of the markers in here, yes?

mccraigmccraig18:11:24

yes - iirc i used to have a marker-atom with content like {<id> <leaflet-marker>} and when markers were updated i would figure out which were stale and remove them, and which were new and add them

dominicm18:11:21

@mccraigmccraig is there a problem with just deleting all of them, and re-inserting all of them?

dominicm18:11:32

I've done that in the past before, the brute-force approach 😄

dominicm18:11:35

(not with leaftlet)

maleghast18:11:50

OK, I will try that after dinner - thanks for confirming that I’d figured out the right place to look, and for a candidate method 🙂 @dominicm - I was wondering same - I am probably going to do that unless I should not.

mccraigmccraig18:11:54

ha, i guess you could do that too @dominicm 😬

maleghast18:11:33

OK cool - have to dash; dinner

mccraigmccraig18:11:47

it's probably not great if you have hundreds to thousands of markers - but probably fine if fewer

dominicm18:11:00

I wondered if markers hold state (open/closed) in which case you wouldn't want to do that

maleghast18:11:17

@mccraigmccraig - I will bear that in mind - I think that the maximum number of markers I would ever have would max out at the 10s of 1000s

mccraigmccraig18:11:00

@maleghast so if you remove and re-create markers on every render then you will be doing 1000s of DOM manipulations every render - it's going to be slow

maleghast18:11:44

Yeah, that’s a good point… is there a “removeFrom” reverse of the .addTo ?

mccraigmccraig18:11:13

can't remember exactly - something like that though

maleghast18:11:21

If I keep an r/atom of markers I’ve created and then remove the ones that aren’t in the list that gets passed in?

maleghast18:11:31

I’ll go have a look

maleghast19:11:31

@mccraigmccraig - Nailed it - thanks!

maleghast19:11:53

(I am deleting all and re-placing the valid ones for now, but I can upgrade it once we go beyond prototype stage(s) to just remove the ones that need removing)

maleghast20:11:54

I’ve just discovered something interesting and unexpected… I am managing the “views” of my SPA with the app-state r/atom, as per a conversation I had a few days back with @mccraigmccraig. However I have just discovered that this approach seems__ to mean that if I navigate away from the page I have essentially just locked / finished (see conversation above ^^) and then navigate back, while the map does render, the markers and borders do not 😞

maleghast20:11:30

If I refresh the whole app the markers and the borders come back, but clearly that’s not going to work… So… Is there a way to force my nested map component to re-run all of its functionality?

maleghast20:11:37

(or is it because I’ve got stale, view-specific state in order to manage the map, and I should make a function to reset all of that state on returning to the view that has the map with borders and markers?)

dominicm20:11:51

component-did-unmount should force the cleanup

dominicm20:11:03

and then component-did-mount should force it to re-create the map

dominicm20:11:17

Are those functions being called?

maleghast20:11:39

Yes they are, but in order to do some stuff with Leaflet (that is stateful and not properly under Reagent / React control), I am using some r/atoms to manage the state of the markers and borders… Refreshing those atoms to starting point state before swap!-ing the app-state r/atom into “Landing Page” view solves the problem perfectly.

dominicm20:11:17

shouldn't component did unmount just wipe the state of the markers & borders?

dominicm20:11:37

or on mount you set to initial state, yeah.

maleghast20:11:53

Yeah, setting them to initial state myself works for this situation… Once I’ve got some breathing room I will experiment with doing something less clunky / more React / Reagent idiomatic, but for now resetting them to initial state works just fine.

maleghast20:11:25

As I understand it I should be avoiding view and / or component specific state if at all possible anyway..?

maleghast20:11:57

(I got the impression that it was broadly a no-no if there was another way to win)

mccraigmccraig20:11:20

in some few cases component-local state makes sense - e.g. grabbing the dom-node for the component in :component-did-mount and holding it for later

mccraigmccraig20:11:42

but generally avoid it