私のシナリオ: サイトは永続的なバックエンドからの行の束を表示します。ユーザーはこれらの行に ajax スタイルで (つまり、現在のサイトを離れずに) 追加できます。送信ボタンが押されたときに、別のページをロードせずに次の 2 つのことが起こるようにします。
- 新しい行を JSON オブジェクトとしてサーバーに送信し、そこで DB に追加する必要があります。
- 新しい行がすぐにテーブルに追加され、表示されるはずです。
さらに、
- ユーザーがサイトを更新すると、テーブルは一連の行を追加した後と同じように表示されます。エラー処理はトリッキーですが、可能であり、私の(現在の)質問ではありません。
私の実装は次のとおりです。
getHomeR = do
records ← runDB $ selectList …
defaultLayout $ do
$(widgetFile "tableWidget")
重要な部分は、これらの行を HTML serversideにレンダリングしたくないということです。クライアントは それらをレンダリングできる必要があるため、それをclientsideにしたいのです! (そして、まったく同じものをまったく同じ方法でレンダリングするクライアント側とサーバー側のコードを維持することは、エラーが発生しやすいアプローチだと思います。)
代わりに、records
ジュリアス補間を介して を JS 変数に入れます。
var records = #{toJSON records}; // the Haskell value containing the data.
renderRow = function(jsonObject) { … }
appendRowToTable = function(row) { … }
$(document).ready(function() {
$.each(records, function(i,v) {
appendRowToTable(renderRow(v));
});
});
これは、私が思いついた問題に対する最もエレガントな解決策でした。レコードを読み取るために別の ajax 呼び出しを行う必要がなくなります。つまり、レコードを DB から新たに取得して JS に追加するルートを追加できることはわかっていますが、それは非効率的だと思います。もう 1 ラウンド必要です。・避けたい旅行。代わりに、JS と HTML は最初のリクエストで構築され、すべてが 1 つの幸せな束として送信されます。リロード時に問題が発生するようになりました。
records
Haskell 変数の内容はページのロード間で変更される場合がありますが、補間は再評価されません。Yesod は、すべての IO 依存補間を含む Julius ファイルが同じままであると想定していますが、そうではありませんでした。records
Haskell 変数の内容とは異なる JavaScript 変数になってしまいますが、これは私には受け入れられません。Yesod に更新を検討させるには、Julius ファイルに触れる必要があります(デフォルトの scaffold を使用しています。それが問題なのでしょうか?)
TL;DR: IO 依存の変数を Julius に補間しますが、これらの変数の内容が変更された場合、Julius ファイルのタイムスタンプを手動で変更するまで、クライアントは更新された JavaScript ファイルを認識しません。IOアクションの内容が変わったときにJavaScriptファイルを再補間してほしいです。あるいは、リクエストごとに変更されると仮定することもできます (つまり、ゼロに設定できる何らかの有効期限はありますか?)
この壁のテキストを読んでくれてありがとう:-)
Michael Snoyman が指摘したように、これは実際には Yesod のバグのようです。この問題を github でオープンしました。