Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Converting Luminus default (~Secretary) to Accountant #52

Closed
WorldsEndless opened this issue Nov 9, 2017 · 14 comments
Closed

Converting Luminus default (~Secretary) to Accountant #52

WorldsEndless opened this issue Nov 9, 2017 · 14 comments

Comments

@WorldsEndless
Copy link

I have a luminus setup for various apps. On one, I now need Accountant's ability to link internally (e.g. as an event handler) without causing a browser refresh. I'm a bit lost in getting the setup working; here's a gist with my existing setup and my attempt to get accountant working. Help would be much appreciated.

https://gist.github.com/WorldsEndless/43c8efc6d4db1ff684d9260fe22ddfc7

@venantius
Copy link
Owner

Your setup looks fine at a glance to me. I normally include a call to (dispatch-current!) at the bottom of the namespace in which accountant is defined so that accountant makes sure the current page is loaded on first load. What exactly isn't working?

@WorldsEndless
Copy link
Author

WorldsEndless commented Nov 9, 2017

I get

Error rendering component (in page)
Error: Assert failed: Invalid Hiccup form: [nil]  (in page) (valid-tag? tag)

This doesn't sound much like an accountant problem, except for the fact that I'm just replacing the hook-browser-navigation! function. In otherwords, my attempt to set up accountant is failing to be the equivalent of the hook-browser-navigation! function.

@venantius
Copy link
Owner

I'm afraid I'm not sure. It sounds like you've got a component that's appearing as [nil "attr"] instead of e.g. [:div "attr"] - probably something that renders based on the routing. I'd start by just stubbing in a :div and debugging from there.

@WorldsEndless
Copy link
Author

I've narrowed the problem down, though I don't know what's causing it. Although I have all those secretary/defroutes in place, but they aren't functioning. The session is supposed to be getting pages sent to its :page value but that isn't happening; hence, reagent is being told to render [nil] because there is no :page value on the session.

Using the repl I can eventually get it to render by executing (secretary/dispatch! "/applicant"). However, after some trial and error, I can verify that (accountant/dispatch-current!) fails to implement (secretary/dispatch! path). In otherwords, given a valid path, I can in the repl run (secretary/dispatch! path) and it works, but it doesn't happen with trying to navigate there by clicking and expecting accountant to do it. I have no explanation, since this println is working:

(accountant/configure-navigation! {:nav-handler (fn [path] (do (println (str "Trying to dispatch via ACCOUNTANT to " path))
                                                               (secretary/dispatch! path)))
                                   :path-exists? (fn [path] (secretary/locate-route path))})

In otherwords, clicking a link causes the println to fire, but to actually get the page to render I have to manually call (secretary/dispatch! "/applicant") to get what I expect.

@venantius
Copy link
Owner

That is extremely unusual. Do you have something else in your application that could be controlling the History?

@WorldsEndless
Copy link
Author

I found the problem. My secretary setup specifies (secretary/set-config! :prefix "#")and then had paths like (secretary/defroute reviews-dashboard-route "/reviews" [] ...). The links end up pointing to the likes of "/#/reviews" and used to be picked up by the hook-browser-navigation! function. However, accountant seems to be receiving a path "/reviews" which then fails the :path-exists? function:

isp.routes> (accountant/path-exists? "/#/applicant")
nil
isp.routes> (accountant/path-exists? "/applicant")
{:action #object[action__37168__auto___39992],
 :params {}, 
 :route #object[secretary.core.t_secretary$core41048]}

In other words, the path accountant receives has the hash in it, but the path secretary expects does not. What is the recommended setup as far as prefixes for an SPA?

@venantius
Copy link
Owner

venantius commented Nov 13, 2017

To be honest, I don't know - I've never developed on an application with prefixed URLs like that. Does setting the prefix as "#/" change anything?

@WorldsEndless
Copy link
Author

Okay; I have it fully functional, probably as intended, by removing the config prefix and having all routes go somewhere without a #.

I have a question, though, about the philosophy of accountant's approach to SPAs; it's probably something I have fundamentally wrong. If I click around the app I navigate fine; but if ever I try reloading a page, or if I follow a link someone sends me from a page within the app, it will always come back with a 404 because the server doesn't know the path (only the js app knows the path). How should this be resolved?

@iku000888
Copy link
Collaborator

I think the easiest solution is to update the server code to constantly return the page (if it is not a resource).

Something along the line of:

(require '[ring.middleware.resource :as r])
(defn handler [req]
  ((r/wrap-resource
    (constantly
     {:status 200
      :body (render home.html)})
    "/")
req))

If SSR is in the scope I imagine you need to do something more ambitious and share the routing between the client/server.

@WorldsEndless
Copy link
Author

Ah; I see. I'll use a catch-all for get requests, and make sure my ajax responses are on different paths. Thanks!

@venantius
Copy link
Owner

@iku000888 beat me to it but I’d have said the same thing. Just whitelist the paths server-side.

@WorldsEndless
Copy link
Author

In spirit, I did something similar (hopefully without unforeseen consequences), which seemed the simplest given the Luminus setup already present:

(defroutes home-routes
  (GET "*" req (home-page (:username req))) ;; No SSR in this app
  (POST "/submit" [application :as req] (let [submission (application/register-submission application)]
                                          (layout/receipt-page submission))))

@venantius
Copy link
Owner

venantius commented Nov 13, 2017

You’ll want to explicitly whitelist your server routes just to get sane 404s from your API endpoints in my experience.

@WorldsEndless
Copy link
Author

Ah; respecting your experience, I went ahead and used the "whitelist" approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants