Yesod: Using typesafe URLs in AJAX calls

2019-04-05 09:15发布

问题:

In my Yesod project i have the following route:

/api/hide/thread/#Text/#Int      ApiHideThreadR   GET

I want to request it on the client side with javascript:

function hideThreadCompletely(threadId, board) {
    $.getJSON("/api/hide/thread/"+board+"/"+threadId, function(data) {
        $('#thread-'+threadId).hide();
    });
}

But i can't use @{ApiHideTHreadR} because Yesod requires it's arguments on compile time. What is the proper solution for this, if i want API URLS to look like api/board/1/1 and not api/board?bid=1&tid=1? Keep using manually-defined URL's like "/api/hide/thread/"+board+"/"+threadId?

回答1:

After some searching I found this discussion, where it is suggested that you add the url as a "data-url" attribute to some element. And then load the url from the element. Something like this:

<div id="thread-1" data-hide-url=@{ApiHideTHreadR}>

var url = $("#thread-1").data("hide-url")


回答2:

What I always do is get rid of the explicit parameter passing in the route call and instead replace it with :

getApiHideThreadR::Handler JSON
getApiHideThreadR = do 
  rawTextParam <- lookupGetParam "text"
  rawThreadId  <- lookupGetParam "table"
  (textParam,threadParam) <- someParseFunction rawTextParam rawThreadId
  ... 

Then you can use regular ajax style:

$.getJSON("@{ApiHideThreadR}",{text:"sometext",tabe:"sometable"},success()...

For more complex get to haskell type requests: https://github.com/yesodweb/yesod/wiki/Convert-get-params-into-a-haskell-record

Is a nice template.



回答3:

You can't use a type-safe route to check at compile-time somthing that is known only at run-time. I suspect you know this too, but that is the only sense I can make of your question. Thus, your only option is doing it manually.