【问题标题】:Javascript Alerts in YesodYesod 中的 Javascript 警报
【发布时间】:2016-01-10 02:08:36
【问题描述】:

我有一个程序,用户可以在其中上传文件,对此文件进行一些验证,如果验证失败,我想通过 javascript 警报消息向用户提供反馈,而不是通过嵌入的消息在 html 本身中。

理想情况下,一旦用户确认了警报消息(单击警报按钮),程序就可以重定向到另一条路线。

不幸的是,重定向似乎立即发生,直到用户单击警报按钮才暂停,因此完全错过了警报。

这是一个简单的 sn-p 说明问题:要求用户选择一个文件。如果是文本文件,则显示其名称,否则会产生警报。

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE MultiParamTypeClasses #-}

import Yesod

import Control.Concurrent.STM (TVar, newTVarIO, readTVarIO, atomically, writeTVar)

import Data.Text (Text)

data App = App (TVar Text)

mkYesod "App" [parseRoutes|
/ HomeR GET POST
/alert AlertR GET
|]

instance Yesod App

instance RenderMessage App FormMessage where
  renderMessage _ _ = defaultFormMessage

getHomeR :: Handler Html
getHomeR = do
    (formWidget, formEncType) <- generateFormPost uploadForm

    App ttxt <- getYesod
    txt      <- liftIO $ readTVarIO ttxt
    liftIO $ print txt
    defaultLayout $ do
     [whamlet| 
        <h1>Text file name: #{txt}
        <p>
        <form method=post action=@{HomeR} enctype=#{formEncType}>
            ^{formWidget} #
            <input type="submit" value="Upload File Name">
     |]

postHomeR :: Handler Html
postHomeR = do
    ((result, _), _) <- runFormPost uploadForm
    case result of
      FormSuccess fi -> do
        app <- getYesod
        case fileContentType fi of
            "text/plain" -> updateFileName app $ fileName fi
            _            -> redirect AlertR
      _ -> return ()   
    redirect HomeR

updateFileName :: App -> Text -> Handler ()
updateFileName app@(App ttxt) txtnew = 
    liftIO . atomically $ writeTVar ttxt txtnew

getAlertR :: Handler Html
getAlertR = do
    defaultLayout $ do
        setTitle "ALERT!"
        toWidgetBody [julius| 
                        alert("Only text files are accepted");
                     |]
    redirect HomeR 

uploadForm = renderDivs $ fileAFormReq "file"

main :: IO ()
main = do
    ttxt <- newTVarIO "nil"
    warp 3000 $ App ttxt

所以这不起作用,并且在 getAlertR 中,redirect HomeR 代码不会“等待”直到用户单击警报按钮(实际上警报甚至不显示)。

为了解决这个问题,我像这样更改了 getAlertR:

getAlertR :: Handler Html
getAlertR = do
    defaultLayout $ do
        setTitle "ALERT!"
        toWidgetBody [julius| 
                        alert("Only text files are accepted");
                        location.assign("@{HomeR}"); 
                     |]
    -- redirect HomeR 

... 工作正常。

但这是我的问题:是否有更“类似Yesod”的方式来做到这一点,而无需在 julius 脚本中进行路由?

【问题讨论】:

    标签: haskell yesod yesod-forms


    【解决方案1】:

    这基本上是一个“Yesod 范围之外”的问题:如果您希望行为基于用户对警报框的响应而发生,则必须在 Javascript 中处理,您的方法可以很好地工作。一旦进入 Javascript 世界,就有数十种/数百种不同的方式来执行此操作(自动使用计时器?在页面上使用通知消息而不是单独的对话框?等等),但是您无法在服务器端进行检查用户单击了不支持 Javascript 的按钮。

    【讨论】:

      猜你喜欢
      • 2012-03-09
      • 1970-01-01
      • 2014-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-16
      • 2011-12-16
      相关资源
      最近更新 更多