Closed Dzoukr closed 4 years ago
amazing job on making routing look so easy! I love it and started to use pretty fast.
Thank Roman :heart: glad to hear you are enjoying this thing
I am familiar with Elmish.Navigation where having such link does not create redirect.
Is it like that by design? Do you know any workaround how to have nicely looking links but keep routing internal without full redirect?
This library isn't anything different than what Elmish.Navigation
is doing under the hood. The problem with path full-redirects is that they happen on the server. Take a look at Vue Router - History Mode (router library for vue.js) which explains the same problem and how to handle this on different types of servers using URL rewrites.
Maybe @marcpiechura can chime in with his experience on how to properly handle this with a dotnet backend?
This library isn't anything different than what Elmish.Navigation is doing under the hood. The problem with path full-redirects is that they happen on the server.
Ok, now I'm confused. :) From my experience using Elmish.Navigation
does not make any request on backend once loaded (the first request is different case, of course). It is somehow catched and handled completely on browser's side.
From my experience using Elmish.Navigation does not make any request on backend once loaded
Neither does Feliz.Router, it is the browser that thinks: "Oh I don't see the hash sign, this must go to the server" but the server only returns the same index.html page which is what this full-redirection is doing.
Do you have a repro example where Elmish.Navigation handles path routes (no hash sign) without this problem?
I have in usage on https://rezervace.mindfulyoga.cz/login (sorry, it is in Czech :)) - both links down does redirection without request to server. Repo is here: https://github.com/Dzoukr/Yobo/blob/master/src/Yobo.Client/Auth/Login/View.fs#L41-L43
Now I see where is it exactly - it uses Navigation.newUrl
which does direct manipulation with history. https://github.com/Dzoukr/Yobo/blob/master/src/Yobo.Client/Router.fs#L49-L52
I think Feliz.Router
doesn't have such direct function, does it?
I think
Feliz.Router
doesn't have such direct function, does it?
Of course it does - Router.navigate
🤦♂
I'm pretty close to resolve it, once done, I'll publish it here just for future reference.
Hmm this is a bit weird because Navigation.newUrl
is implemented like this:
module Navigation =
/// Push new location into history and navigate there
let newUrl (newUrl:string):Cmd<_> =
[fun _ -> history.pushState((), "", newUrl)
let ev = CustomEvent.Create(NavigatedEvent)
window.dispatchEvent ev
|> ignore ]
and Router.navigate
uses the internal Router.nav
function after encoding the parts:
module internal Router =
let nav xs (mode: HistoryMode) : Elmish.Cmd<_> =
Cmd.ofSub (fun _ ->
if mode = HistoryMode.PushState
then history.pushState ((), "", encodeParts xs)
else history.replaceState ((), "", encodeParts xs)
let ev = document.createEvent("CustomEvent")
ev.initEvent (customNavigationEvent, true, true)
window.dispatchEvent ev |> ignore
)
They are doing the same when it comes to history.pushState
so it should just works when you use onClick.
I just realized you use both href
and onClick
for the <a></a>
tag in your application. I haven't seen this before tbh, not sure which on is being fired first: theOnClick
handler was preventing the default behavior of the anchor, so maybe that is why the navigation is happening via the Navigation.newUrl and not via the href?
Just to be sure that I understand it correctly, for you pathMode
does work in onClick
events without full redirection? (It does work in the test project included in the repo)
I think I have it!!!
You can create custom function goToUrl
open Feliz.Router
open Fable.Core.JsInterop
let goToUrl (e: MouseEvent) =
e.preventDefault()
let href : string = !!e.currentTarget?attributes?href?value
Router.navigate href |> List.map (fun f -> f ignore) |> ignore
and then you can have:
Html.a [
prop.text "Click me"
prop.href (Router.format("some-sub-path"))
prop.onClick goToUrl
]
which works exactly as expected (without making request)
Just to be sure that I understand it correctly, for you pathMode does work in onClick events without full redirection? (It does work in the test project included in the repo)
Yes, it does, but I need to handle it via custom Msg
like you do in you demo repo here : https://github.com/Zaid-Ajaj/Feliz.Router/blob/master/demo/App.fs#L26
which works exactly as expected (without making request)
Awesome 🎉 I will probably add it to the docs
I need to handle it via custom
Msg
You can do that like this: (also removing the ugliness of interop / commands)
type Msg =
| NavigateTo of string
let update msg state =
match msg with
| NavigateTo href -> state, Router.navigate(href)
let goToUrl (dispatch: Msg -> unit) (href: string) (e: MouseEvent) =
e.preventDefault()
dispatch (NavigateTo href)
let render state dispatch =
let href = Router.format("some-sub-path")
Html.a [
prop.text "Click me"
prop.href href
prop.onClick (goToUrl dispatch href)
]
Hey, that's even way more cleaner! 🎉
Perfect, thanks a lot for all the help (and patience 😄)!!
No worries man! :smile:
Hello friend,
amazing job on making routing look so easy! I love it and started to use pretty fast. There is still one think I probably fully don't understand. When creating link for routing in
pathMode
topage/sub-page
, I have two options:onClick
to link element which dispatch custom command likeNavigate
and in update function dorouter.navigate
. Downside of this approach is there is nohref
in link so user cannot see in bottom browser bar where is it heading to + it isn't so SEO friendly.router.format
to generatehref
for link, but clicking on those will trigger full redirect (combining withonClick
doesn't help)I am familiar with
Elmish.Navigation
where having such link does not create redirect.Is it like that by design? Do you know any workaround how to have nicely looking links but keep routing internal without full redirect?
Thanks for any help.