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

just-path removes # #183

Open
NOBLES5E opened this issue May 23, 2018 · 9 comments
Open

just-path removes # #183

NOBLES5E opened this issue May 23, 2018 · 9 comments

Comments

@NOBLES5E
Copy link

Since just-path removes # so that a path /#/about-me becomes /, which makes the following code not working

(def bidi-route
  ["/" {"#/about-me"     :about-me
        "#/publications" :publications
        "#/teaching"     :teaching}])

(bidi/path-for bidi-route :publications)  ; => /#/publications

(bidi/match-route bidi-route "/#/publications") ; => nil
@NOBLES5E
Copy link
Author

I would suggest match-route function assumes the path provided is just the path we want to match without modification. If we want to remove the # or query parameters etc we should call just-path function by ourselves.

@dmichulke
Copy link

dmichulke commented Jul 2, 2018

As a "workaround" (not meaning to say this is a bug in bidi because on the server side this well-defined behavior) - when using accountant, you can just

(defn- unprefixed
  [path]
  (if (clojure.string/starts-with? path "/#")
    (subs path 2)
    path))

and then, e.g.,

  (accountant/configure-navigation!
   {:nav-handler (comp (fn [path] 
     ;; here goes your old nav handler
     ) unprefixed)
    :path-exists? (comp (fn [path] 
     ;; here goes your old exists handler
     ) unprefixed})

You must then rewrite the routes without the leading /#

@SevereOverfl0w
Copy link
Contributor

SevereOverfl0w commented Jul 2, 2018

Depending on what you're trying to achieve, there's different solutions here. js/location.hash gives the result "#/about-me", meaning that the solution is to do (subs js/location.hash 1) for the URL.

However, if you have intentions of doing URLs like /about#/me as well as /#/foo, then doing this won't let you distinguish between the two. In this case you will need a scheme for distinguishing between them, I suppose you could drop the # in most cases, unless you had both /about#/me and /#/about/me and you wanted them to be different.

The intention of just-path was to prevent tripping over URLs with query params & other transient artifacts, particularly with ring. The correct behavior here is quite hard to get right. Ultimately bidi isn't intending to work on location hashes, but the ideal is to work on pure paths.

One could argue that if a location hash is found in a URL then use it. But that falls down because:

  • Location hashes can be used for in-page navigation (linking within elements on a page)
  • Users could break routing by adding a location hash to the URL

@dmichulke
Copy link

@SevereOverfl0w

Yes, of course. I was considering only empty paths before that hash. But the general solution is to use js/location.hash (didn't know this one) which returns everything beginning with the hash.

As stated above, I agree you shouldn't change the bidi behavior, just maybe mention how it can be nicely resolved in a SPA.
I posted the workaround because it's probably a usual problem people programming SPAs will have yet it wasn't immediately obvious (at least to me on a Monday after lunch) how to resolve it.

@SevereOverfl0w
Copy link
Contributor

Documentation may well be the best way to resolve this. We're having a focus on documentation at JUXT right now, so bidi may be a good candidate for improving as a result of that.

@Folcon
Copy link

Folcon commented Mar 25, 2020

Personally I'm a little puzzled by this, wouldn't a url fragment caused by an #section-name also be preserved on the server side? Or does that already occur?

Anyway, what is the expected way to resolve this?

@SevereOverfl0w
Copy link
Contributor

Url fragments aren't sent to the server, ever.

@Folcon
Copy link

Folcon commented Mar 26, 2020

Yea, my mistake, I've seen enough url fragment laden urls get routed that it never occurred to me to check if the browser was actually forwarding them...

Looking at the js/location.hash approach, not certain how to make this work, here's my example:

(def routes ["/"
             {"" :home
              "#/login"  :login
              "#/logout" :logout
              true :not-found}])

So I route to :login

(bidi/path-for routes :login)
#_=> "/#/login"

window.location.hash gives me "#/login" which when I check for matches gives me:

(bidi/match-route routes "#/login")
#_=> nil
(bidi/match-route routes "/login")
#_=> {:handler :not-found}
(bidi/match-route routes "/#/login")
#_=> {:handler :home}

So not quite clear how that works...

@HaskellZhangSong
Copy link

BTW, this issue also trapped me.

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

5 participants