Я новичок в Yesod и, кажется, полностью потерян с помощью виджетов, Handlers, Hamlets, Whamlets и что у вас есть! Вот что я пытаюсь сделать:Как сделать IO в виджете/Гамлете, на который ссылается defaultLayout?
- Каждая страница на моем сайте должна иметь Navbar, что приводит меня к мысли, что правильное место для реализации этого должна быть
defaultLayout
- Теперь этот Navbar нужно отобразить некоторую информацию, полученную от действия ввода-вывода (это скорее вызов RPC, который дает эти данные, более конкретно).
Поэтому я пытался писать следующую функцию в Foundation.hs
(макет коды является основным шаблоном yesod-sqlite
подмостей):
nav = do
globalStat <- handlerToWidget $ A2.getGlobalStat NWT.ariaRPCUrl
$(whamletFile "templates/navbar.hamlet)
A2.getGlobalStat :: IO GlobalStatResponse
Вот что template/navbar.hamlet
выглядит следующим образом:
<nav .navbar .navbar-default>
<div .container-fluid>
<p .navbar-right .navbar-text>
<span>
#{A2.glDownloadSpeed globalStat}
<i .glyphicon .glyphicon-arrow-down>
<span>
#{A2.glUploadSpeed globalStat}
<i .glyphicon .glyphicon-arrow-up>
<span .label .label-success>
On-the-watch
Вот что default-layout-wrapper.hamlet
выглядит следующим образом:
<!-- SNIP -->
<body>
<div class="container">
<header>
^{nav}
<div id="main" role="main">
^{pageBody pc}
<!-- SNIP -->
Вот что defaultLayout
выглядит следующим образом:
defaultLayout widget = do
master <- getYesod
mmsg <- getMessage
pc <- widgetToPageContent $ do
addStylesheet $ StaticR css_bootstrap_css
$(widgetFile "default-layout")
withUrlRenderer $(hamletFile "templates/default-layout-wrapper.hamlet")
Однако код отказывается компилироваться с одним типом ошибки после другого. Я пробовал много комбинаций hametFile
, whamletFile
, handerToWidget
, liftIO
, даже если разместить функцию nav внутриdefaultLayout
, но ничего не работает. По моему мнению, мой текущий код должен скомпилировать, но я, очевидно, не понял, как работают типы Yesod-Core.
Как я могу заставить это работать? И что еще более важно, какую концепцию я неправильно понял?
Edit 1:
Пытались модификации функции nav
к следующему:
nav :: Handler Html
nav = do
globalStat <- liftIO $ A2.getGlobalStat NWT.ariaRPCUrl
$(hamletFile "templates/navbar.hamlet")
Но это приводит к следующему несовпадения типа в defaultLayout
на линии с withUrlRenderer
:
Couldn't match type ‘HandlerT App IO Html’
with ‘Text.Hamlet.Render (Route App) -> Html’
Expected type: HtmlUrl (Route App)
Actual type: Handler Html
In the first argument of ‘Text.Hamlet.asHtmlUrl’, namely ‘nav’
In a stmt of a 'do' block: Text.Hamlet.asHtmlUrl nav _render_a2ZY0 (intero)
Редакция 2:
попытался изменить тип подписи nav
к:
nav :: Widget
nav = do
globalStat <- liftIO $ A2.getGlobalStat NWT.ariaRPCUrl
$(hamletFile "templates/navbar.hamlet")
Но это приводит к новому типу-рассогласования, в одной и той же линии:
Couldn't match type ‘WidgetT App IO()’
with ‘Text.Hamlet.Render (Route App) -> Html’
Expected type: HtmlUrl (Route App)
Actual type: Widget
In the first argument of ‘Text.Hamlet.asHtmlUrl’, namely ‘nav’
In a stmt of a 'do' block: Text.Hamlet.asHtmlUrl nav _render_a350l (intero)
Edit 3:
. Вот соответствующий фрагмент из -ddump-splices
:
\ _render_a28TE
-> do { asHtmlUrl (pageHead pc) _render_a28TE;
id ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "\n");
asHtmlUrl (pageBody pc) _render_a28TE;
id ((Text.Blaze.Internal.preEscapedText . Data.Text.pack) "\n");
asHtmlUrl testWidget2 _render_a28TE }
Тип (pageHead pc)
и (pageBody pc)
является HtmlUrl (Route App)
Отредактированным мой вопрос к сообщению нового кода фрагменты, основанные на подходе «liftIO». Теперь проблема заключается в том, что использование '^ {nav}' в шаблоне 'default-layout-wrapper', похоже, не очень хорошо составлено. –