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

Routing #5

Open
mpdairy opened this issue Sep 28, 2017 · 3 comments
Open

Routing #5

mpdairy opened this issue Sep 28, 2017 · 3 comments

Comments

@mpdairy
Copy link

mpdairy commented Sep 28, 2017

Have you thought about a clever way to do routing with Concur? I'm planning on using something like servant-router to parse a Servant API in the client and then load the correct corresponding widget, and something like ghcjs-servant-client to generate functions to jump to the route (maybe just by doing a JS History pushState).

Then I think I'd just need a loop at the bottom that listened for changes to the location/history state and loaded the new widget / killing the old one.

But the big downside of this is that whenever I want to route a change I can't use the nice monad flow to do menus like in your example, plus it seems pretty bad to be able to jump to any other route within any widget; it could turn to spaghetti real fast.

@ajnsit
Copy link
Owner

ajnsit commented Sep 28, 2017

Well I haven't implemented any routing apps yet. At the most basic level I can think of the following scheme. However it would be good to brainstorm on an ideal API.

So let's say we have data Route = A | B | C. And we want to show widgetA, widgetB, widgetC respectively. Then it could look like this -

getRoute = <IO CODE TO FETCH AND PARSE CURRENT URL>
main = do
  route <- getRoute
  case route of
    A -> widgetA
    B -> widgetB
    C -> widgetC

That would handle the routing only once in the beginning. So to handle routing changes in real time we can put in a short circuit operation at the top level -

getRoute = <IO CODE TO FETCH AND PARSE CURRENT URL>
awaitRouteChange = <IO CODE TO AWAIT A PAGE CHANGE>
displayCurrentRoute = do
  route <- getRoute
  case route of
    A -> widgetA
    B -> widgetB
    C -> widgetC

main = forever $ displayCurrentRoute <|> awaitRouteChange

This will abort the current widget when the route changes, and redraw the widget for the new route.

@mpdairy
Copy link
Author

mpdairy commented Oct 4, 2017

I ended up using the ghcjs-servant-router library (https://github.com/plow-technologies/servant-ghcjs-router), but I modified it so all the routes return a concur Widget and the initRouter function runs runWidgetInBody . forever on the widget returned by the route. With that I can do nested routes and wrap widgets around nested routes to provide menus or back buttons. If anybody wants me to make a nice fork of it with a demo, let me know.

@ajnsit
Copy link
Owner

ajnsit commented Oct 5, 2017

@mpdairy that is awesome! An example demo would be great!

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

No branches or pull requests

2 participants