2014-05-05 6 views
7

Sto provando a creare una pagina semplice che utilizza AJAX per comunicare con il server (Yesod). Finora sono riuscito a passare i dati dal server, ma non so come ottenere i dati dei client con il gestore del server (putJsonpR).Hot per ottenere dati da una richiesta Ajax con yesod

Questo è quello che ho finora:

{-# LANGUAGE OverloadedStrings, DeriveGeneriC#-} 
    {-# LANGUAGE QuasiQuotes  #-} 
    {-# LANGUAGE RecordWildCards #-} 
    {-# LANGUAGE TemplateHaskell #-} 
    {-# LANGUAGE TypeFamilies  #-} 

    import Yesod 
    import Database.PostgreSQL.Simple 
    import Database.PostgreSQL.Simple.FromRow 
    import Database.PostgreSQL.Simple.ToRow 
    import Database.PostgreSQL.Simple.ToField 
    import Data.Aeson 
    import Data.Text (Text) 
    import Control.Applicative 
    import Control.Monad 
    import GHC.Generics 

    data HelloWorld = HelloWorld 

    mkYesod "HelloWorld" [parseRoutes| 
    /HomeR GET 
    /json/#Int JsonR GET 
    /json JsonpR PUT 
    |] 

    instance Yesod HelloWorld 

    data Person = Person { 
     personId :: Int, 
     name :: String, 
     age :: Int 
    } deriving (Show,Generic) 

    instance FromJSON Person 
    instance ToJSON Person 

    instance FromRow Person where 
     fromRow = Person <$> field <*> field <*> field 

    instance ToRow Person where 
     toRow d = [ toField (personId d), toField (name d), toField (age d)] 

    getConnectionString = do 
     cnn <- connect defaultConnectInfo { 
       connectHost = "127.0.0.1" 
       , connectPort = 5432 
       , connectUser = "postgres" 
       , connectPassword = "123456" 
       , connectDatabase = "tst" 
       } 
     return (cnn) 

    getPerson id = do 
     cnn <- getConnectionString 
     xs <- query cnn "select \"PersonId\", \"Name\", \"Age\" from \"Person\" where \"PersonId\" = ?" (Only (id :: Int)) :: IO [Person] 
     return (head xs) 

    getHomeR :: Handler() 
    getHomeR = sendFile typeHtml "staticpage.html" 

    getJsonR :: Int -> Handler Value 
    getJsonR personId = do 
     person <- liftIO $ getPerson personId 
     returnJson $ person 

    putJsonpR :: Handler Value 
    putJsonpR = do 
     person <- parseJsonBody_ :: Handler Person 
     returnJson $ person 

    main :: IO() 
    main = warp 3000 HelloWorld 

E questa è la pagina HTML:

<html> 
     <head> 
      <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script> 
      <script type="text/javascript"> 
       function getPerson() { 
        $.ajax({ 
        url: "/json/" + 1, 
        success: function (data) { 
         alert (data.personId + " - " + data.name + " - " + data.age); 
        }, 
        dataType: "json" 
        }); 
       } 

       function save() { 
        $.ajax({ 
        url: "/json", 
        type: "PUT", 
        data: { "personId": 123, "name": "from gui", "age": 123 }, 
        success: function (data) { 
         alert (data.personId + " - " + data.name + " - " + data.age); 
        }, 
        error: function(xhr, status, error) { 
         alert(xhr.responseText); 
        }, 
        dataType: "json" 
        }); 
       } 
      </script> 
     </head> 
     <body> 
      <input type="button" onclick="getPerson()" value="get" /> 
      <br /> 
      <br /> 
      <br /> 
      <input type="button" onclick="save()" value="put" /> 
     </body> 
    </html> 

ho ottenuto l'errore AJAX whith un messaggio: "la lettura non riuscita: non è un valore JSON valida"

Inoltre, c'è un modo per produrre tutto ciò che ho ricevuto dalla richiesta AJAX?
Qualcosa di simile:

putSomethingR = do 
     liftIO $ print $ whateverCameFromAjax 
     -- rest of handler 

risposta

4

Sul lato "GET", dal momento che non si utilizza persistenti modelli ma db livello SQL da Database.PostgreSQL.Simple.query, utilizzando i reali identificatori di database, risolve l'errore

getPerson id = do 
    cnn <- getConnectionString 
    xs <- query cnn "select \"id\", \"name\", \"age\" from \"person\" where \"id\" = ?" (Only (id :: Int)) :: IO [Person] 
    return (head xs) 

Sul lato "PUT", v'è un errore di analisi ajax sul vostro script jquery staticpage.html, corretto quando si racchiudere i "Dati" campo tra apici:

function save() { 
     $.ajax({ 
     url: "/json", 
     type: "PUT", 
     data: '{ "personId": 123, "name": "from gui", "age": 123 }', 
     ... 
     dataType: "json" 
     ... 

3 °. È possibile log l'output ajax con

$(logDebug) (show whatEverCameFromAjax) 

da un MonadLogger esempio Monade, se si utilizza il patibolo Yesod.

+2

Cosa devo inserire invece 'whateverCameFromAjax' per farlo loggare? – edgecrusher

5

Ho messo insieme a sample of doing this on FP Haskell Center. Il codice è incluso anche qui sotto.

Il problema con quello che hai inizialmente scritto è nel codice Javascript. I tuoi parametri su jQuery dicono di creare un corpo di richiesta con codifica URL. È necessario eseguire il rendering manuale del testo JSON in testo e disattivare l'elaborazione con processData: false.

{-# LANGUAGE OverloadedStrings #-} 
{-# LANGUAGE QuasiQuotes  #-} 
{-# LANGUAGE TemplateHaskell #-} 
{-# LANGUAGE TypeFamilies  #-} 
import   Yesod 
import   Yesod.Form.Jquery (YesodJquery (urlJqueryJs)) 
import Data.Conduit 
import qualified Data.Conduit.Text as CT 
import qualified Data.Conduit.List as CL 
import qualified Data.Text as T 

data App = App 

mkYesod "App" [parseRoutes| 
/HomeR GET 
/echo-body EchoBodyR PUT 
|] 

instance Yesod App 
instance YesodJquery App 

getHomeR :: Handler Html 
getHomeR = defaultLayout $ do 
    setTitle "Yesod + Ajax" 
    getYesod >>= addScriptEither . urlJqueryJs 
    [whamlet| 
     <button #echo>Echo body 
    |] 
    toWidget script 

script = [julius| 
$(function(){ 
    $("#echo").click(function(){ 
     $.ajax({ 
      // sending a JSON encoded body 
      contentType: "application/json", 
      // don't process the body, we'll render data into a valid string 
      processData: false, 
      url: "@{EchoBodyR}", 
      type: "PUT", 
      // notice the usage of stringify here 
      data: JSON.stringify([{name:"Alice",age:25}, {name:"Bob",age:30}]), 
      success: function(data) { 
       alert(data.body); 
      }, 
      // this only refers to the data type of the *returned* data 
      dataType: "json" 
     }); 
    }); 
}); 
|] 

putEchoBodyR :: Handler Value 
putEchoBodyR = do 
    texts <- rawRequestBody $$ CT.decode CT.utf8 =$ CL.consume 
    return $ object ["body" .= T.concat texts] 

main :: IO() 
main = warpEnv App 
Problemi correlati