QA@IT

Railsでテキストフィールドに入力された文字列を使ってリンクする

3850 PV

たとえば、メールアドレスを入力してsubmitボタンを押すと、そのアドレスをURLとして/foo/email@address.comのようなURLにGETで飛ばしたいのです。

現状、

= form_tag '/foo' do
  = text_field_tag :email
  = submit_tag :send
:javascript
  $('form').submit(function() {
    window.location.href = '/foo/' + $(this).find('input#email').val();
    return false;
  });

のようなやり方でやってるのですが、やりたいことのシンプルさに見合わない複雑さだと感じています。とくにformタグとjQueryのセレクタの結びつきが汎用的でありません。

もっとうまい方法はないでしょうか?

回答

こんな感じでいかがでしょう。

# application.js.coffee
$ ->
  $('form[data-append-to-action]').submit ->
    $this = $(this)
    field = $this.find("[name=#{$this.data('append-to-action')}]")
    window.location.href = "#{$this.attr('action')}/#{field.val()}"
    false
= form_tag '/foo', 'data-append-to-action' => 'email' do
  = text_field_tag :email
  = submit_tag :send
編集 履歴 (0)
  • これ、気に入りました。ありがとうございます。form_tagにdata attributeを指定すると期待した挙動になる、というのは直感的で良いと思いました。さらにこれをラップしたヘルパーとかも簡単につくれますしね。jsとhtmlテンプレートはソースコード上の距離が遠いので、なるべく密結合した書き方は避けたいのですが、これならjsの存在を忘れてどこでも使えそうです。 -

汎用的に、ということであれば jQuery のカスタムイベントを使ってみてはいかがでしょうか。

submit のときにゴニョゴニョとしたい部分をイベントとして分離することで、コードのセマンティクスとしてはだいぶスッキリするかと思います。

JavaScript

$("form").submit(function() {
  // 当該 form 配下の input タグにバインドされた preSubmit イベントを起動
  var preSubmitEvent = jQuery.Event("preSubmit");
  $(this).find(":input").trigger(preSubmitEvent, [this]);
  if (!preSubmitEvent.reault) {
    return false;
  }
});

$("input#email").bind("preSubmit", function(e, formElement) {
  window.location.href = "/foo/" + this.value;
  return false;
});

$("form").submit(...); の部分を共通の JavaScript に切り出しておけば標準的に preSubmit イベントが利用できるような形になりますね。

編集 履歴 (2)
  • window.location.href じゃないと URL に ?email= が残っちゃいませんかね? -
  • 確かに…。回答を修正させていただきます。 -
  • preSubmitイベントを定義してやる、というのは、たしかに一つのアイデアですね。ただ結局 $("input#email") でHTMLとjQueryのセレクタが密結合してしまう問題が解決されてなかったので、そこをうまくできれば、こちらのほうがより汎用的な解決方法になったかもしれませんね。 -

大して変わらないのですが、formのactionを書き換える方が結びついてる感じがしますかね?

  $('form').submit(function() {
    var $this = $(this);
    $this.attr('action', '/foo/' + $this.find('input#email').val() );
  });
編集 履歴 (0)
  • たしかにactionを書き換えるほうが直感的ですね。しかしそうすると、POSTになってしまうんです。Post/Redirect/Getパターンの信者としては、POSTでは決してrenderしないことにこだわりたいところです。で、このケースだとform_tagにmethod: :getを指定する必要があるのですが、そうするとURLに?utf8=✓とか色々と変なものが出てきてしまいます。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。