Reputation: 518
I am quite new to Yesod and currently try to develop a frontend website and a backend restful webservice. To access the API from the website I use AJAX requests. For the URLs of the requests I want to use shakespearean template like calls:
$.ajax({
url: '@{PersonR}',
type: 'GET',
contentType: "application/json",
data: JSON.stringify({...}),
success: function (data) {...}
});
On the backend site the route to my PersonR handler is defined as follows:
/api/person/#Int/get PersonR GET
For this to work the handler has a signature like
getPersonR :: Int -> Handler Value
However now the julius template needs a parameter to be a valid. I experimented a bit and found that I can directly use haskell code also in @{...}. Maybe I missed that point in the doku. Question 1: Is there a way to tell that one of the parameters could be given in JavaScript? Maybe with a renderer to output something like this:
function(var1){return '/api/person/'+var1+'/get';}
I think this lacks the point of type safety though. Which leads to my second question (which kinda negates the first): Is there any other way to achieve getting data into the URLs on the client side?
Upvotes: 2
Views: 181
Reputation: 7707
I haven't used this package much, but yesod-js-routes
seems like it fits the bill. Basically the package takes your routes file and generates Javascript functions you can use to create the URLs.
The package hasn't seen active development in awhile, but based on testing it still works fine. It's not on Hackage, but it's one file, so I just copied it into my project (I also needed to add import Prelude
to that file, and add mtl
to my build-depends section of the Cabal file). The README of the project covers the basic integration of the package you need to do.
Here's some example output. For this routes file:
/static StaticR Static appStatic
/auth AuthR Auth getAuth
/favicon.ico FaviconR GET
/robots.txt RobotsR GET
/ HomeR GET POST
/comments CommentR POST
/jsRoutes JSRoutesR GET
/test/#Text/#Integer TestR GET POST
I got this Javascript:
;
var jsRoutes = {}; /* Subsite not supported */ ; /* Subsite not supported */ ;
jsRoutes.FaviconR = {
get: function() {
return {
method: "get",
url: "/favicon.ico/"
};
}
};
jsRoutes.RobotsR = {
get: function() {
return {
method: "get",
url: "/robots.txt/"
};
}
};
jsRoutes.HomeR = {
get: function() {
return {
method: "get",
url: "/"
};
},
post: function() {
return {
method: "post",
url: "/"
};
}
};
jsRoutes.CommentR = {
post: function() {
return {
method: "post",
url: "/comments/"
};
}
};
jsRoutes.JSRoutesR = {
get: function() {
return {
method: "get",
url: "/jsRoutes/"
};
}
};
jsRoutes.TestR = {
get: function() {
return {
method: "get",
url: "/test/" + arguments[0] + "/" + arguments[1] + "/"
};
},
post: function() {
return {
method: "post",
url: "/test/" + arguments[0] + "/" + arguments[1] + "/"
};
}
};
For a route like TestR
, you can call:
jsRoutes.TestR.get("a",2).url
to return
"/test/a/2/"
Unfortunately, neither the generated Javascript nor Javascript the language is doing anything to protect against e.g. passing 3 arguments to that function, or passing arguments of the wrong type. I don't know what your expectations are, but the Javascript code generation looks simple enough that you could improve what's generated.
Upvotes: 1