Giter VIP home page Giter VIP logo

servant-router's Introduction

servant-router

servant-router routes a URI given a Servant API and an appropriate handler. In web applications, this is used to make single page applications (SPAs) with front-end routing, letting you share portions of your Servant APIs between the client and server.

servant-router does not depend on reflex or any GHCJS packages. It's intended to be a general purpose URI router on any platform. Combined with reflex-dom, servant-reflex, and reflex-dom-contrib, this makes for a very satisfactory front-end Haskell experience.

You can see examples of using servant-router on both the frontend and the backend in the examples directory.

servant-router's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

servant-router's Issues

runRoute incompatible with relative URI's

This took me so stupidly long to figure out!!

runRoute will return FailFatal on any relative URI's, per the behaviour of Network.URI.parseURI. I think the behaviour of parseURI has been changed in network-uri 2.6 or something.

Anyway, this is very problematic, because Reflex.Dom.Contrib.Router.routeSite returns relative URI's, and thus doesn't work with this library.

I think the solution is simply to change runRoute to use parseURIReference instead. There might also need to be a preprocessor check for old versions of nework-uri..?

Missing README.md

@ElvishJerricco you have moved package into subfolder but README.md stays in repo root and yet it's listed in servant-router/servant-router.cabal as extra-source-files.
I guess it's better be fixed.
BTW what was the motivation of that move?

Any real reflex app example?

I was trying to create muli-page app with this package but I just don't get how does it work with normal reflex logic.
I my SPA I just use mainWidget which wraps MonadWidget into IO returning () as a result. And routeSite wants events as handler outputs. Thus the example from README with just el "div" $ text "Sample text" added into and handler fails to compile with

    /home/qrilka/ws/example-app/src/Main.hs:41:7: error:
        • Could not deduce: m ~ IO
          from the context: MonadWidget t m
            bound by a type expected by the context:
                       MonadWidget t m => String -> m (Event t String)
            at src/Main.hs:(23,8)-(45,23)
          ‘m’ is a rigid type variable bound by
            a type expected by the context:
              forall t (m :: * -> *).
              MonadWidget t m =>
              String -> m (Event t String)
            at src/Main.hs:23:8
          Expected type: m ()
            Actual type: IO ()
        • In a stmt of a 'do' block:
            mainWidget $ do { el "div" $ text "Sample text" }
          In the expression:
            do { mainWidget $ do { el "div" $ text "Sample text" };
                 return never }
          In a case alternative:
              Left _
                -> do { mainWidget $ do { el "div" $ text "Sample text" };
                        return never }
        • Relevant bindings include
            handler :: forall t1 a t2 a1.
                       (t1 -> ExceptT RoutingError m (Event t a))
                       :<|> (Maybe t2 -> ExceptT RoutingError m (Event t a1))
              (bound at src/Main.hs:24:7)

servant-router and reflex: using the returned `Event t Text`

Hi, thanks for this library, it's conceptually very clean. I have only an issue which it's stopping me from using it fully: in your tutorial there is the snippet:

main = routeSite $ \uri -> do
  let handler = books :<|> search
      books i = do
        ...omitted...
        return never
      search Nothing = do
        ...omitted...
        return never
      search (Just keywords) = do
        ...omitted...
        return never

Now, in this example you always return never, but I'd like to actually use the text signal I'm returning to navigate away from the page (it enables me to use more sophisticated navigation).

So, let's say I trigger a text, signalling my intent to move to the page at that url. Unfortunately, for how routeSite is implemented, the address changes in the title bar, but the actual page doesn't change! How could I change the structure in the tutorial so that the firing of the returned Event t Text also change the page I'm in?

Here's the code of routeSite: as you can see, it only sets the url:

routeSite
    :: (forall t m. MonadWidget t m => Text -> m (Event t Text))
    -> IO ()
routeSite siteFunc = runWebGUI $ \webView -> do
    w <- waitUntilJust currentWindow
    path <- getWindowLocation w
    doc <- waitUntilJust $ liftM (fmap castToHTMLDocument) $
             webViewGetDomDocument webView
    body <- waitUntilJust $ getBody doc
    attachWidget body (WebViewSingleton webView) $ do
      changes <- siteFunc (T.pack path)
      setUrl $ T.unpack <$> changes
      return ()

Do you have any suggestion or a more complex example that makes use of the returned event?

No version tags in git repo?

I see on hackage versions that 0.7.1, 0.8.0 and 0.8.1 for this package. As there is no changelog for it I wanted to check github version tags but didn't find any. It would be great if you could add them or maybe use some other convenient way to make changes.easily trackable

Not working?

I have a simple page and returning a new URI from my handler has no effect. I'm using latest Reflex-DOM and reflex-dom-contrib on GitHub as of today.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.