Fork me on GitHub
#keechma
<
2016-07-04
>
roberto16:07:08

is there a way to change the URL from within a controller?

roberto16:07:18

I have a scenario where I have a component with lists of items, a component that displays a selected item, and a search component. When I type in the search bar, it fetches data form the server and modifies the list of items. But I want to add the search query to the url. Currently I’m sending an event from the search component to trigger the xhr call. But can’t find a way to update the URL.

roberto17:07:33

yeah, I figured that out, now I’m stuck with something else

roberto17:07:42

I redirect, and it gets parsed in the params function

roberto17:07:55

but I can’t do a controller/execute from there

mihaelkonjevic17:07:37

you have two options:

mihaelkonjevic17:07:54

1. reset search controller on every change of search params and make a request

mihaelkonjevic17:07:37

2. handle the :route-changed command in the handler function

mihaelkonjevic17:07:09

:route-changed will be sent to every running controller every time something in the url is changed

mihaelkonjevic17:07:50

so your params function could only check for the existence of the search params and then you can handle it manually in the handler function

mihaelkonjevic17:07:45

route params that were present when the controller was started are readable from (:route-params controller)

roberto17:07:08

ah, yeah, I think I found a way. I trigger a “redirect” within the function that gets called to do the search. I don’t need to worry about parsing the route in the params function to trigger another call.

roberto17:07:48

I was doing something silly, took me a while to figure out how things work. I was triggering a do-search message, which redirected.

roberto17:07:10

and then I was trying to trigger the real search message in the params function

roberto17:07:45

I noticed one of my controllers gets started over and over tho, there is probably something wrong. Everytime my search params is triggered, the start function for one of my other controllers gets triggered.

mihaelkonjevic17:07:22

how does the params function look for that controller?

roberto17:07:37

(params [_ route]
    ;;Only run this controller when the route is home or "recordings".
    (prn "ROUTE IN RECORDINGS: " route)
    (let [route-data (:data route)]
      (if (or (and (= (:section route-data) "recordings")
                   (:page route-data))
              (= (:section route-data) "home"))
        {:section (:section route-data)
         :page    (:page route-data)
         :query    (:query route-data)}
        nil)))

mihaelkonjevic17:07:06

you’re returning query inside the object so that’s probably why

mihaelkonjevic17:07:25

it’s different every time the route changes

roberto17:07:50

ok, so everytime the return value of params changes, the start function is called?

roberto17:07:00

I thought it was only called on initialization of the controller

mihaelkonjevic17:07:08

yeah, it shuts down the old controller

mihaelkonjevic17:07:13

and initializes the new one

mihaelkonjevic17:07:20

it’s basically restarting the controller

mihaelkonjevic17:07:57

stop will be called on the old controller instance first

roberto17:07:58

ohhhh, ok. So , to sum it up, if params changes, we get a new controller.

roberto17:07:17

hmmm, ok, I see. Thanks, this is very helpful.

mihaelkonjevic17:07:07

yeah, if you want to manually handle the query params (without controller restart) read the original value from (:route-params controller) and then listen to the :route-changed command inside the handler function

roberto17:07:26

I think I can use (:route-params this) to get access to the query instead of returning it from params

mihaelkonjevic17:07:28

although I would probably split it to a separate search controller

roberto17:07:44

yeah, I have a separate search controller

roberto17:07:01

but the list controller has to re-fetch the list from the server based on the changes in the query

roberto17:07:22

so I still want to inspect the routes, but I don’t want to be restarting the controller, right?

mihaelkonjevic17:07:09

there are more patterns you can use… you could have the search controller sending the message to the list controller whenever it restarts

mihaelkonjevic17:07:44

so you would do something like (send-command this [:list-controller-topic :query] query-data)

mihaelkonjevic17:07:51

from the start function of the search controller

roberto17:07:31

ok, but that would mean the search controller gets restarted with every change in the query, right?

roberto17:07:49

restarting the controller doesn’t re-render the component, right (unless the data changes)?

mihaelkonjevic17:07:33

nope, and you can send the search command up to the search controller, debounce it there and redirect after let’s say 200ms

roberto17:07:06

coo, that sounds much more cleaner. I was trying to debounce in the component itself.

roberto17:07:09

which got nasty

mihaelkonjevic17:07:45

yeah, that’s why controllers have the handler function, so you can use channels for that kind of logic

roberto18:07:34

to send a command to another controller, how do I specify the name of the controller?

roberto18:07:44

Do I need a handle on the instance of the controller?

roberto18:07:29

nevermind, I see I can get access to it from the app-db

roberto18:07:55

hmmm, any idea why this isn’t working?

(let [recordings-ctrl (get-in @app-db-atom [:internal :running-controllers :recordings])]
    (controller/is-running? recordings-ctrl)) ;; This is returning true  
    (controller/send-command recordings-ctrl :search-recording [args]))

roberto18:07:08

I’m getting a Uncaught Error: nth not supported on this type cljs.core/Keyword error

mihaelkonjevic18:07:41

so when you use send command

mihaelkonjevic18:07:50

it always gets routed through the controller manager

mihaelkonjevic18:07:03

so you need to specify both topic and command

mihaelkonjevic18:07:11

so instead of :search-recording

mihaelkonjevic18:07:23

it would be [:controller-topic :search-recording]

mihaelkonjevic18:07:54

where are you sending the command from?

mihaelkonjevic18:07:01

if you’re sending it from another controller

roberto18:07:02

from another controller

mihaelkonjevic18:07:13

you don’t need to get the controller instance

mihaelkonjevic18:07:17

just send it on the correct topic

mihaelkonjevic18:07:33

topic being whatever was the key in the controllers map when starting the app

mihaelkonjevic18:07:51

so you wound send it like this:

mihaelkonjevic18:07:09

(controller/send-command this [:controller-topic :command-name] args)

roberto18:07:45

that works