質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.48%

  • Ruby on Rails 4

    2457questions

    Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

  • CoffeeScript

    144questions

    CoffeeScriptはプログラミング言語です。シンタックスシュガーの導入により、JavaScriptのコードに変換された後動作します。JavaScriptに比べ、可読性と簡潔性が向上しています。

CoffeeScriptでchangeイベントが動作しません

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,184

sorachi77

score 9

前提・実現したいこと

Ruby on Railsで記述しているselectタグの変更を検知するイベントを、CoffeeScriptで記述したい。

発生している問題・エラーメッセージ

ページ読み込み時に一度実行されるが、ブラウザからselectの選択を変えても、JSコンソールには何の反応もない。

該当のソースコード

<%= select_tag('pay_category', options_from_collection_for_select(@categories, :category, :category)) %><br>
do ->
  console.log('test')

  $('.pay_category').on 
       'change': console.log('change')

chromeのJSコンソール出力結果

①ページ読み込み時
 test
 change

②select要素変更時
 ①と変化なし

試したこと

CoffeeScript公式サイトのTRY機能でコンパイルしたところ、以下のようにコンパイルされました。

(function() {
  console.log('test');
  return $('.pay_category').on({
    'change': console.log('change')
  });
})();

最後の処理にreturnが付くのがCoffeeScriptの仕様と勉強したのですが、それによって即時関数が終了してしまっている(?)ことが原因かと考え、色々検索してみたのですが解決することができず、ご質問させていただきました。

初歩的な質問となってしまい、大変申し訳ございません。
もし解決方法をご存知でしたら、お手数をおかけいたしますがよろしくお願い致します。

2016/5/1 21:30追記

皆様ご回答いただきましてありがとうございました。

お恥ずかしながら、classとidの指定方法を混合しておりました。
いただいたご回答をもとに、以下のとおり修正致しました。

$('#pay_category').on 'change', ->
     console.log 'change'

しかし、これでselectの選択を変更してもJSコンソールに変化がなく、もっと根本的なところに原因があるのかと、次の実験を行いました。

【実験①:シンプルに要素の取得だけ試す】

以下のコードを追記し、要素の取得ができているかどうかの実験を行いました。

Viewにただのテキストボックスを追加。

<%= select_tag('pay_category', options_from_collection_for_select(@categories, :category, :category)) %><br>
<input type="text" id="textone" value="textone初期値">

CoffeeScriptに以下を追加。

do ->
  console.log('test')

 #追加
  test = $('#textone').val()
  console.log(test)

    $('#pay_category').on 'change', ->
        console.log 'change'

しかし、textoneのログ結果はundifinedでした。
ですので、根本的にフォームの要素を取得できていないことがわかりました。

【実験②:Viewにscriptを書いて実験】

Viewファイルの1番下に以下を追加。

<script>
    var test;
    test = $('#textone').val();
    console.log(test);
</script>

そうすると、JSコンソールには以下の通り表示されました。

 textone初期値

よって、やはりCoffeeScriptとViewの接続がうまくいっていないように思えます。

【実験③:applicasion.jsに書いて実験】

本来は推奨されないと読んだのですが、AssetPipelineに問題があるのかと思い、application.jsに実験①と同様のコードを書いた実験も行いました。
しかし、結果はundifinedとなりました。
ですので、原因はView←→CoffeeScriptにありそうです。

せっかくご回答いただきましたのに、別の所に原因がありまして大変申し訳ございませんでした。
ご回答をいただきましてから本原因の調査もしてみたのですが、解決する情報を見つけることが出来ませんでした。
もしまだお付き合いいただけましたら、本原因もご存知でしたら、ご教授いただけると幸いです。

環境はmacにvagrantで作ったcentos環境を使用しており、今回が初railsですのでgemなどは足りないものが出てきたらググッて追加しているところであります。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 5

+5

$('.pay_category')....

は class="pay_category" となっている要素について処理を設定しています。

画面の html ソース上で selectタグの部分を確認してみてください。
おそらく id="pay_category" となっているのではと思います。
そうなっていたなら、 $('#pay_category')... と書く必要があります。

select タグの部分に id や適切なクラスが設定されていなければ、 select_tag の使い方をしらべて
class を指定するように書いて、そのクラスに対して、coffeescript で処理を設定するようにすれば良いと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/01 22:11

    >katoy様
    ご回答ありがとうございます。
    コードの修正を行ったのですが、私の調査不足で他に原因がありそうなことが判明致しました。
    大変お手数をおかけして恐縮ですが、もしお時間がありましたら本文に追記いたしましたので、ご覧いただけると幸いでございます。

    キャンセル

  • 2016/05/02 20:26

    >katoy様
    無事解決することが出来ました。
    ご回答いただきましてどうもありがとうございました。

    キャンセル

checkベストアンサー

+1

jQueryのonメソッドのチェンジとして指定されているのが、
質問文のままではundefinedという値になってしまっています。
(changeに入る時に実行後の戻り値を使う→console.logの戻り値は常にundefined)

なのでこうすれば通るんじゃないですかね?

do ->
  console.log('test')

  $('.pay_category').on 
       'change': -> console.log 'change'

追記部分

そもそもCoffeeスクリプトで書いたconsole.logが出力されている時点でつなぎ込みは正常に行われています。

根本のブラウザ+JavaScriptの仕様として、
JavaScriptはscript要素で読み込まれた瞬間実行されます。
script要素が書かれている内容のJavaScriptの動作が全て終わらない限り、以降の要素は基本的に1行も解析されません。

上記仕様により、
例えばCoffeeScriptで生成されたJavaScriptのファイルがhead要素の配下にある場合、
まだレンダリングされる前の存在しないbodyの中身を必死に探して何もないという結果が帰ってきます。

ブラウザはbodyの中身を全て解析し終わった後、loadイベントを発行します。

body要素のonLoad属性に発火して欲しい処理を記載したり、
jQueryのready機能を使うことでDOM構造の構築が終わってから処理を始める事ができます。
(body要素のonLoad属性は上書きされて古い設定が用意に消えるので、jQueryのready機能を使うことです)

ファイルを下記のように変更すれば動くと思いますので試してみてください。

$ ->
  console.log('test')

 #追加
  test = $('#textone').val()
  console.log(test)

  $('#pay_category').on 'change', ->
      console.log 'change'

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/01 22:11

    >miyabi-sun様
    ご回答ありがとうございます。
    コードの修正を行ったのですが、私の調査不足で他に原因がありそうなことが判明致しました。
    大変お手数をおかけして恐縮ですが、もしお時間がありましたら本文に追記いたしましたので、ご覧いただけると幸いでございます。

    キャンセル

  • 2016/05/02 20:25

    >miyabi-sun様
    教えていただいた方法で解決することが出来ました!
    お忙しい中何度も教えていただき、深く感謝申し上げます。
    これからもrailsの勉強に励みたいと思います。
    どうもありがとうございました。

    キャンセル

+1

select要素のクラスはきちんとpay_categoryになっていますでしょうか。別途でクラスやIDを振ったほうが確実かもしれません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/01 22:09

    >maisumakun様
    ご回答ありがとうございます。
    お恥ずかしながらidとclassの指定方法を混合しておりました。
    コードの修正を行ったのですが、私の調査不足で他に原因がありそうなことが判明致しました。
    大変お手数をおかけして恐縮ですが、もしお時間がありましたら本文に追記いたしましたので、ご覧いただけると幸いでございます。

    キャンセル

  • 2016/05/02 20:25

    >maisumakun様
    無事解決することが出来ました。
    ご回答いただきましてどうもありがとうございました。

    キャンセル

+1

2点あります。

  1. select_tagに引数で渡した名前はidになります。今回ですと<select id="pay_category" ...となっているはずです。idですのでjQueryからセレクタ指定で取得するとは$(#pay_category')とする必要があります。
  2. jQueryのon()の使い方が間違っているようです。引数は、on(イベント名, コールバック関数)またはon({イベント名: コールバック関数)という形です。なので、->で無名関数を作って渡さないと動かないと思います。(miyabi-sunさん、サンクス)

上記を踏まえて、下記のように修正すれば動くようになるかと思います。お試しください。

do ->
  console.log('test')

  $('#pay_category').on 'change', ->
    console.log('change')

なお、うまくいかないときは、ブラウザ上で変換されたHTMLやJavaScriptが想定通りなのかを確認すると良いと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/01 19:22 編集

    raccyさんの回答を見てドキッとなったので調べてみました。

    http://js.studio-kingdom.com/jquery/events/on
    このページの1.7バージョンで追加の箇所でこんな記述を見かけたので試してみました。
    > .on( events-map [, selector] [, data] ) 1.7追加

    下記のコードを打ち込んで試したら確かに動いたので、単純に関数を指定していない事が原因となりそうです。
    $($0).on({'click': function(){console.log(123);}})

    キャンセル

  • 2016/05/01 19:48

    > miyabi-sunさん
    まじっすか。って公式APIのドキュメントをよくよんだら二つ目にありますね。例文でも見たこと無かったので、勘違いしてました。関数じゃ無いからが原因の一つですね。

    キャンセル

  • 2016/05/01 19:57

    私もjQueryはオブジェクトが引数になるケースが多いので、
    きっとonも同様の動作するんじゃねーのくらいの認識なのでびっくりしました(笑
    引数が文字列なら〜、配列なら〜…って動きはあんまり良くない気もしますね。

    キャンセル

  • 2016/05/01 22:12

    >raccy様
    ご回答ありがとうございます。
    コードの修正を行ったのですが、私の調査不足で他に原因がありそうなことが判明致しました。
    大変お手数をおかけして恐縮ですが、もしお時間がありましたら本文に追記いたしましたので、ご覧いただけると幸いでございます。

    キャンセル

  • 2016/05/02 20:26

    >raccy様
    無事解決することが出来ました。
    ご回答いただきましてどうもありがとうございました。

    キャンセル

0

coffeeScriptは関数を書いた場合、関数内の最後に定義されたものを自動的にreturnする仕様になっており、イベント処理時にそのまま書くと、関数式が返ってきます。それを避けるには、最後に明示的にreturnを書かないと動作しなかった気がします。
すいません、最初の質問のみ読んで回答しています。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/02 20:26

    >DaisukeSakai様
    無事解決することが出来ました。
    ご回答いただきましてどうもありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Ruby on Rails 4

    2457questions

    Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

  • CoffeeScript

    144questions

    CoffeeScriptはプログラミング言語です。シンタックスシュガーの導入により、JavaScriptのコードに変換された後動作します。JavaScriptに比べ、可読性と簡潔性が向上しています。