@roberto: you can add meta data on collections and named items
thanks, it is what I ended doing.
another question, in the Place My Order example, specifically this https://github.com/keechma/keechma-place-my-order/blob/66cd3138897f72f9e683dae2e562610c55cd8984/client/src/client/controllers/restaurant.cljs#L24
the :recordings :current
entity is being attached some meta data. I noticed this overwrites the meta data for :recordings :list
.
is that the expected behavior?
that shouldn’t be happening. I’ll investigate and get back to you
oh, I think I know why, because the entire app-db-atom is being reset!
is there a way to just update it instead of resetting?
but ti should return the whole new version of atom with only the (relevant) part of the data changed.
hmmm, for me it is changing the entire atom, deleting the :list
and only :current
is present
it deletes only the meta data or the data too?
also how are you retrieving the meta data in your ui component?
both
I’m using get-collection-meta
yeah, that’s the right way
but only for troubleshooting, was wondering why my list disappeared when I selected an item
that definitely shouldn’t be happening
you are seeing this behavior only in your app or in place-my-order app too?
i haven’t tried place-my-order
, planning on doing that today. Seeing it on my app right now, which is tightly based on place-my-order
can you paste the code that shows that behavior?
I have a list on the left side, and the selected item is displayed on the right side
1 second, they are two controllers
this is the function in the controller for displaying the individual item:
(defn update! [app-db-atom updater]
(reset! app-db-atom (updater @app-db-atom)))
(defn load-recording
[app-db-atom slug]
(update! app-db-atom
#(edb/insert-named-item % :recordings :current {} {:is-loading? true}))
(let [recording (edb/get-item-by-id @app-db-atom :recordings (js/parseInt slug))]
(when-not recording
(go
(let [req (<! (http/get (str "/api/recordings/" slug)))
meta {:is-loading? false}
[success data] (unpack-req req)]
(update! app-db-atom
#(edb/insert-named-item % :recordings :current data meta)))))))
this is the what loads the list:
(defn load-collection
[entity list app-db-atom req]
(do
(reset! app-db-atom
(edb/insert-collection @app-db-atom entity list [] {:is-loading? true})))
(go
(let [[is-success? body] (unpack-req (<! req))
data (if is-success? (:recordings body) [])
max-pages (.ceil js/Math (/ (:total body) page-size))
meta (if is-success?
{:is-loading? false
:current-page (:current-page body)
:total (:total body)
:max-pages max-pages
:next-page (next-page (:total body) max-pages (:current-page body))}
{})]
(reset! app-db-atom
(edb/insert-collection @app-db-atom entity list data meta)))))
(def load-recordings (partial load-collection :recordings :list))
this is the list controller:
(defrecord Controller []
controller/IController
(params [_ route]
;;Only run this controller when the route is home or "recordings".
(let [route-data (:data route)]
(when (or (and (= (:section route-data) "recordings")
(:page route-data))
(= (:section route-data) "home"))
route-data)))
(start [this params app-db]
(if (= "home" (:section params))
(controller/redirect this {:section "recordings" :page 1})
(when (:page params)
(controller/execute this :load-recordings params)))
app-db)
(handler [_ app-db-atom in-chan out-chan]
(go (loop []
(let [[command args] (<! in-chan)]
(case command
:load-recordings (let [url (str "/api/recordings?page=" (:page args))
req (http/get url)]
(load-recordings app-db-atom req))
(get-collection app-db-atom))
(when command (recur))))))
(stop [_ _ app-db]
(edb/remove-collection app-db :recordings :list)))
the default case is just this:
(defn get-collection
[app-db-atom]
(prn "METAS: " (edb/get-collection-meta @app-db-atom :recordings :list))
(prn "COLLECTION: " (edb/get-collection @app-db-atom :recordings))
(edb/get-collection @app-db-atom :recordings :list))
which i placed there because my list kept disappearing
this line won’t return anything (prn "COLLECTION: " (edb/get-collection @app-db-atom :recordings))
because you need to give the name of the collection
if :recordings
is the entity name
you need to pass the :list
as the collection name too
even if I give the name of the collection, it returns an empty list
this is the controller for the selected item:
(defrecord Controller []
controller/IController
(params [this route]
(let [route-data (:data route)
page (:section route-data)
slug (:slug route-data)]
(when (and (= page "recordings")
(not (nil? slug)))
route)))
(start [this params app-db]
(let [slug (get-in params [:data :slug])]
(controller/execute this :current-recording slug))
app-db)
(handler [this app-db-atom in-chan out-chan]
(go (loop []
(let [[command args] (<! in-chan)]
(case command
:current-recording (load-recording app-db-atom args)
:backup-to-vimeo (backup-to-vimeo app-db-atom args)
nil)
(when command (recur)))))))
for what it’s worth, I think it is because of the update!
function
it is using reset!
which, well, will replace the entire atom
yeah, but it should update just the part of the internal map. I’ll definitely have to check what’s going on
btw you can shorten the code inside the handler
functions by using the dispatcher
function https://github.com/keechma/keechma-todomvc/blob/master/src/keechma_todomvc/controllers/todos.cljs#L28
ah, nice
ah, and the update!
function in that example is using swap!
instead of reset!
will try that
I’m not using EDB in that app
that’s why
ah, ok
EDB has it’s own internal structure which is why I’m replacing the whole atom
I’m probably understanding something wrong, isn’t app-db-atom completely replaced with a new value by reset!
? Or is this not a typical clojure atom?
it is, but the map inside should retain the old data.
it seems that edb is removing some data it shouldn’t
yeah, if I reach into the atom manually, I can see the list there
(:entity-db @app-db-atom)
@roberto I think this part is the problematic
it seems that you’re calling get-collection
before load-recordings
is finished
get-collection
is supposed to be the default case
so, when an item is selected load-recordings
shouldn’t be called, because it is already there
but you load only one item when the item is selected, right?
so basically what needs to happen is: both controllers need to load their data, list and current
and they will be merged inside the EDB
so you will always have only one version of the current recording
but, you still need to load the collection :list and named item :current
which is different from the place-my-order app
because it doesn’t have the master-detail view
it’s either the list of restaurants or one restaurant
do you see both requests (list and current) in the console when you have the detail page open?
what do you mean by ‘requests’?
xhr rquests?
yeah
no, it is not supposed to issue an xhr request
because it is already loaded.
so the flow is the following: initial view displays the master list, that does an xhr request
then when we select an item from that list, we don’t do any xhr requests because the items are already downloaded
oh, there’s another problem I just noticed
you’re returning the whole route-data
from the params function
which causes the controller to be restarted
controller manager checks what is returned from the params function
hmmm, so what should params return?
Receives the route-params and returns either the params for the controller or nil
only the subset of data your controller cares about
oh
this seems to be a documentation issue.
basically, controller checks what is returned from the params function
and based on that decides what to do with the controller
Whenever the URL changes, the manager controller will do the following: It will call params function of all registered controllers It will compare returned value to the last returned value (returned on the previous URL change) Based on the returned value it will do the following: If previous value was nil and current value is nil it will do nothing If previous value was nil and current value is not nil it will start the controller If previous value was not nil and current value is nil it will stop the controller If previous value was not nil and current value is not nil but those values are same it will do nothing If previous value was not nil and current value is not nil but those values are different it will restart the controller
ok, this is helpful
thank you