Hatena::ブログ(Diary)

ザリガニが見ていた...。 このページをアンテナに追加 RSSフィード

2007-06-23 最近覚えた便利なオプション

:disable_withで処理中を明確にして二重送信を防止

フォームに入力した内容をサーバー送信する時、送信ボタンを押してから処理に時間がかかると不安になる。(特にファイルをアップロードする時など。)ユーザーによっては、2回、3回と送信ボタンを押しまくるかもしれない...。不要な操作は、サーバーにも負荷がかかるし、きっとユーザーもイライラしているはず。そんな時は、submit_tagの:disable_withオプションで手軽に解決できた!

  • 以下のように:disable_with=>'アップロード処理中...'と設定しておけば...
    • ボタンを押すと、操作できない状態に変化して、二重送信が防止できる。
    • 同時にボタンの表示が[アップロード処理中...]に変更され、ユーザーにフィードバックできる。
<%= start_form_tag({:action => 'create'}, :multipart => true) %>
  <%= render :partial => 'form' %>
  <%= submit_tag "アップロード", :disable_with=>'アップロード処理中...' %>
<%= end_form_tag %>

f:id:zariganitosh:20070623071136p:image

ボタンを押すと...

f:id:zariganitosh:20070623071134p:image

単純だけど、効果が大きい。これから多用しそう。

ajax更新の場合

  • 調子に乗って、CSVサーバーの多くの送信ボタンに:disable_withオプションを設定してみたら...
    • form_remote_tagブロックの中で:disable_withオプションを使うと、ajax更新でなく、ページ遷移の更新になってしまった。
<%= form_remote_tag :update => 'list_update', 
                    :submit => 'list_params', 
                    :url => {:action => 'list_update'} %>
  <%= render :partial => 'filter_form' %>
  <%= submit_tag "フィルターを実行", :disable_with=>'フィルターを実行中...' %>
<%= end_form_tag %>
  • そうなのです。ajax更新なんだから、:loadingと:completeオプションを使えば良いのだ!
<%= form_remote_tag :update => 'list_update', 
                    :submit => 'list_params', 
                    :url => {:action => 'list_update'}, 
                    :loading => "$(filter_submit).disabled=true; $(filter_submit).value='フィルターを実行中...'", 
                    :complete => "$(filter_submit).disabled=false; $(filter_submit).value='フィルターを実行'" %>
  <%= render :partial => 'filter_form' %>
  <%= submit_tag "フィルターを実行", :id => 'filter_submit' %>
<%= end_form_tag %>

:disable_withの中身

  • ちなみに、disable_withオプションを設定すると、以下のように展開される。
  • onclick="this.disabled=true;this.value='アップロード処理中...';this.form.submit();"が付加されている。
<%= submit_tag "アップロード", :disable_with=>'アップロード処理中...' %>

展開後は...
<input name="commit" onclick="this.disabled=true;this.value='アップロード処理中...';this.form.submit();" type="submit" value="アップロード" />

なるほど。そのうち、自分流にヘルパメソッドに定義して、拡張しても良いかもしれない。例えば、イージケータがクルクル回るとかね。

ChenChen 2009/09/15 16:17 ご説明有難う御座います。
でも、zariganitoshさんの通りで実装して、例外が発生しました。
下記はわたしが実装したソース:
<% form_remote_tag :update => 'execute', :url => { :action => 'execute' } , :loading => "$('submit_button').value = 'Sending...';$('submit_button').disable();" do %>
<%= file_field_tag 'file', :size => 60%><br />
<%= submit_tag 'XXXXXX',:id=>'submit_button',:onclick=>'submitform();' %>
<% end %>
以上のソースなら、問題があります。データの登録できましたが、画面の移行を行いません。原因が分かりません。
zariganitoshさんは原因が分かったら、ご指導お願いいたします。
PS:私は日本語が下手なので、すみません。

zariganitoshzariganitosh 2009/09/18 05:30 すいません。返信が遅くなりました。既に解決されているかもしれませんが...
> データの登録できましたが、画面の移行を行いません。

おそらく、以下の様に動作していると思います。
Ajax更新なので、form_remote_tag :update=>'execute'... で指定したid="execute"の部分のみ更新されます。
もし、Chenさんのerbソースの中で、id="execute"がどこにも指定されていないと、
更新される部分はsubmitボタンの Sending... のみになります。
そして、form_remote_tagの中で、:complete=>"$('submit_button').value =..."の指定がないので、
disableな Sending... ボタンの状態は、いつまでも続いてしまいます。
自分であれば、以下のように書くと思います。

# View
<% form_remote_tag :update=>'execute', :url=>{ :action => 'execute' } ,
:loading=>"$('submit_button').value = 'Sending...';$('submit_button').disable();",
:complete => "$('submit_button').value = 'Complete';$('submit_button').disabled=false;" do %>
<%= file_field_tag 'file', :size=>60 %><br />
<%= submit_tag 'XXXXXX',:id=>'submit_button',:onclick=>'submitform();' %>
<% end %>

<div id="execute">
--update test--
</div>

# Controller
def execute
# DB処理
render :text=>'--execute--'
end

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/zariganitosh/20070623/1182551690