Fork me on GitHub
#hoplon
<
2017-07-04
>
flyboarder00:07:19

@thedavidmeister am I understanding correctly that you are sorting input fields?

thedavidmeister01:07:01

based on what the user types into the input field

thedavidmeister01:07:17

or clicks, actually in my app it is number fields

thedavidmeister01:07:25

so they can click up and down in the widget

flyboarder01:07:28

Iā€™m not sure I understand, you want to sort the form fields as you type into them?

thedavidmeister01:07:56

it can be on blur, same bug happens

thedavidmeister01:07:15

the exact event that updates the backing data isn't important based on my testing

flyboarder01:07:12

@thedavidmeister can you provide a snippet? From your issue description this sounds like correct behaviour

thedavidmeister01:07:25

@flyboarder there is a PR with passing/failing tests

thedavidmeister01:07:42

you can see from different commits the issue

flyboarder01:07:09

@thedavidmeister ok so I just did a bunch of reading of the old issue and the new one you opened, from what I can tell you are looking for lenses

thedavidmeister01:07:33

i don't think so?

flyboarder01:07:41

since 2-way data binding isnt allowed in hoplon/javelin, the correct way to manage the state would be to use an intermittent cell

thedavidmeister01:07:46

can you give an example of how i should set this up?

flyboarder01:07:35

@thedavidmeister do you have a snippet of your element?

thedavidmeister01:07:59

+(deftest ??sorting-elements
 + (async done
 +  (let [data (j/cell {:a 1 :b 1 :c 2})
 +        sorted-data (j/cell= (sort-by (fn [[k v]] [v k]) data))
 +        el (h/div
 +            (h/for-tpl [[k v] sorted-data]
 +             (h/input
 +              :data-k k
 +              :value [(j/cell= (get data k)) sorted-data]
 +              :input #(swap! data assoc @k (int @%)))))
 +        read-vals (fn [el]
 +                   (map
 +                    #(-> % js/jQuery .val)
 +                    (-> el js/jQuery (.find "input") array-seq)))
 +        read-ks (fn [el]
 +                 (map
 +                  #(-> % js/jQuery (.attr "data-k"))
 +                  (-> el js/jQuery (.find "input") array-seq)))]
 +   (-> js/document .-body (.appendChild el))
 +
 +   (h/with-dom el
 +    (is (= ["1" "1" "2"] (read-vals el)))
 +    (is (= [":a" ":b" ":c"] (read-ks el)))
 +
 +    (-> el js/jQuery (.find "input") .first (.val 3) (.trigger "input"))
 +    (is (= {:a 3 :b 1 :c 2} @data)) ; passes
 +    (is (= [":b" ":c" ":a"] (read-ks el))) ; passes
 +    (is (= ["1" "2" "3"] (read-vals el))) ; fails with ["3" "2" "3"]!
 +    (done)))))

thedavidmeister01:07:18

soz, that's an old commit

thedavidmeister01:07:21

(deftest ??sorting-elements
 + (async done
 +  (let [data (j/cell {:a 1 :b 1 :c 2})
 +        sorted-data (j/cell= (sort-by (fn [[k v]] [v k]) data))
 +        el (h/div
 +            (h/for-tpl [[k v] sorted-data]
 +             (h/input
 +              :data-k k
 +              ; :value [v data]
 +              :value v
 +              :input #(swap! data assoc @k (int @%)))))
 +        read-vals (fn [el]
 +                   (map
 +                    #(-> % js/jQuery .val)
 +                    (-> el js/jQuery (.find "input") array-seq)))
 +        read-ks (fn [el]
 +                 (map
 +                  #(-> % js/jQuery (.attr "data-k"))
 +                  (-> el js/jQuery (.find "input") array-seq)))]
 +   (-> js/document .-body (.appendChild el))
 +
 +   (h/with-dom el
 +    (is (= ["1" "1" "2"] (read-vals el)))
 +    (is (= [":a" ":b" ":c"] (read-ks el)))
 +
 +    (-> el js/jQuery (.find "input") .first (.val 3) (.trigger "input"))
 +    (is (= {:a 3 :b 1 :c 2} @data)) ; passes
 +    (is (= [":b" ":c" ":a"] (read-ks el))) ; passes
 +    (is (= ["1" "2" "3"] (read-vals el))) ; fails with ["3" "2" "3"]!
 +    (done)))))

thedavidmeister01:07:12

@flyboarder the problem is that the final sorted data looks like [1 2 3] but the UI shows [3 2 3] because the cell containing 1 for b does not change so it does not trigger do! even though it "moves" somewhere else in the DOM

thedavidmeister01:07:13

at least i think that is what is going on

thedavidmeister01:07:52

i don't have a good understanding of the nitty gritty going on under the hood, just that if v doesn't change then do! is not triggered and so you see a "stale" DOM element somewhere

thedavidmeister01:07:32

i'm totally willing to accept this as the "correct" behaviour if i get an example showing how i "should" be handling this situation šŸ™‚

flyboarder01:07:34

@thedavidmeister right so your second state should be outside your loop-tpl, any state which changes while in a tpl should be inside the cell it tracks

thedavidmeister01:07:15

what do you mean?

flyboarder01:07:34

the issue is you are tracking two sets of state, which is a no no

thedavidmeister01:07:57

can you please provide a code example?

flyboarder01:07:32

yeah im trying to come up with something XD

flyboarder01:07:06

this is how I like to remember -tpl macros, the cell they track is a collection of element states

flyboarder01:07:13

the data you want to sort is actually an attribute value of the element state

thedavidmeister02:07:15

but isn't it common to want to sort a collection based on the attributes of the things in the collection?

thedavidmeister02:07:55

actually, i'm not aware of any other way to sort a collection šŸ˜›

flyboarder07:07:40

Sort seems to be a thing we should be able to generalize, I'll throw together a pattern and do a snippet, I think there are a few cells/attributes we can provide to simplify this.

thedavidmeister08:07:01

@flyboarder happy to explore ideas

thedavidmeister08:07:04

ultimately i think that if there are things in the DOM that are read/write, there will continue to be edge cases where you need to to be able to trigger do! based on more context than just "does this one cell change?"

thedavidmeister08:07:05

i think "generalising sort" is just kicking the can down the road

thedavidmeister08:07:10

but it might help us get a better grasp on the details of the problem and what our options are

thedavidmeister08:07:33

unless you make it so rearranging cells actually rearranges DOM elements, rather than simply mutating attributes in place to simulate position changes

cycle33723:07:04

hey guys, I'm using a basic lens to update a value in app-state

cycle33723:07:26

(defn path-cell [c path]
  (cell= (get-in c path) (partial swap! c assoc-in path)))

(def page (path-cell app-state [:page]))

cycle33723:07:11

and then I'm deref-ing page as an argument to an ajax-request function to get me paginated responses from backend

cycle33723:07:08

question is, why doesn't it automatically trigger a rerender when I click on a different page and swap! page (:page query-params) ?

cycle33723:07:07

it is my understanding that it should automatically request a new response from backend

micha23:07:00

you can do like (cell= (pr :updating app-state)) to see when the lens is triggering a change

micha23:07:31

when you update page it should update app-state

micha23:07:53

and that should propagate to any other formulas, watches, etc that depend on app-state

cycle33723:07:29

@micha neat, I see now that page gets updated but data stays the same

cycle33723:07:50

so my app-state has :page 1 and :data [] and after first request it populates data

cycle33723:07:18

how can I reset! :data with a new request ?

micha23:07:36

if i understand your setup correctly, i think i'd have the update fn in the path-cell lens call the remote endpoint

micha23:07:56

and then have the XHR or whatever populate the app-state cell with its results

micha23:07:18

also with this method you have options for error handling

micha23:07:50

like the XHR could populate a different cell or a different place in the app state with info about any errors if it fails

micha23:07:53

things like that

micha23:07:12

and a "loading" indication so the user knows things are going on in the background

micha23:07:41

basically i would make it so that app-state isn't updated until the remote request has been resolved

cycle33723:07:23

I'm going to try what you suggested