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

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

ただいまの
回答率

90.99%

  • JavaScript

    13873questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

動的に追加した要素にaddEventListnerを設定する方法

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 880

SugiuraY

score 166

いつもお世話になっております。

動的に追加した要素にaddEventListnerを設定する方法がわからないのです。
調べてもJqueryでの方法は多く出てくるのですが、生のJavascriptでは出てこないので質問させていただきました。

試しにコードを作成してみたのですが、動的に生成された要素elm_2が存在しないためaddEventListner propertyがNullですと返ってくるのかと推察しました。

jqueryの$(document).on('click','hoge',function)のように動的に生成された要素にイベントを設定したいということになります。
よろしくお願いいたします。

<body>

<button id="btn_1">btn</button>

      <script type="text/javascript">
      function adding() {
      var elm_add = document.createElement('button');
      elm_add.id = "hoge";
      elm_add.textContent='btn added';
      var objBody = document.getElementsByTagName("body").item(0);
      objBody.appendChild(elm_add);
      }
      var elm = document.getElementById("btn_1");
      elm.addEventListener("click", adding, false);

      </script>

      <script type="text/javascript">

      function warnings (){
        alert('it works! congraturations!!')
      }


      var elm_2 = document.getElementById("hoge");
      elm_2.addEventListener("click", warnings, false);
     //Uncaught TypeError: Cannot read property 'addEventListener' of null
      </script>
</body>
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

checkベストアンサー

+2

以下のように行ってみてはいかがでしょうか?

<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>タイトル</title>
</head>
<body>
<button id="btn_1">btn</button>
<script>
    var num = 0;

    function adding() {
        var elm_add = document.createElement('button');
        elm_add.id = "hoge" + num;
        elm_add.textContent = 'btn added';
        var objBody = document.getElementsByTagName("body").item(0);
        objBody.appendChild(elm_add);
        elm_add.addEventListener("click", warnings, false);
        num++;
    }

    var elm = document.getElementById("btn_1");
    elm.addEventListener("click", adding, false);

    function warnings() {
        alert('it works! congraturations!!')
    }
</script>
</body>
</html>

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/10/15 22:31

    ご回答ありがとうございます。
    最初のelmに設定した、イベント処理関数の中に追加の要素の定義とそれに対する新たなイベントを設定するということですね。こちらでも動作を確認ができました、ありがとうございます。
    JavaScriptの処理の順番を考えた場合には、動的な要素の生成にまたaddEventListnerを設定することと、最初のイベント処理内(adding)でこれを設定することに大きな違いが無いように感じます。
    もしよろしければ、勉強のためにどのような動きに違いがあるのか簡単にご教示いただくことは可能でしょうか?
    わがままを申し上げて申し訳ございませんが、よろしくお願い申し上げます。

    キャンセル

  • 2017/10/15 22:39

    > JavaScriptの処理の順番を考えた場合には、動的な要素の生成にまたaddEventListnerを設定することと、最初のイベント処理内(adding)でこれを設定することに大きな違いが無いように感じます。

    少し意味が分からないので、もし良ければもう少し詳しく何が分からないか教えていただけませんか?

    キャンセル

  • 2017/10/15 22:52

    コメントありとうございます。抽象的で申し訳ございません。
    1) #btn_1のbutton要素をクリックすると動的に#hoge button要素を生成するイベントが発生
    2) #hoge button要素をクリックするとalert("it works!....")を表示するイベントが発生
    という順番かと思います。私のコードとご提示いただいたの違いは2)を外に出すか、1)の中のコールバック(イベント)関数に含めるかの違いかと思います。なぜその違いでJavascriptは#hoge button要素の認識するかしないかの違いが生じるのかがその構造または処理の過程が私のわからない点になります。
    そもそも動的に生成した要素はそれ以下のコードでgetElementByIdしても捕まえることができないのは、イベントバブリングと関連があるのでしょうか。。

    一方例えば、下記のkei344様のように、生成した後の要素は捕まえることができないとしてdocumentオブジェクトから改めて全体を読み込みイベントオブジェクトから改めて特定の要素を取得して処理を記載するという点はなんとなく直感的に理解はできるのですが、、、
    初心者の質問にお付き合いいただき、誠に申し訳ございませんが
    何卒、よろしくお願い申し上げます。

    キャンセル

  • 2017/10/15 23:14

    実行(今回ではイベント登録)時点で設定対象の要素が存在するかどうかの違いかと思いますが、いかがでしょうか...?的外れなことを言っていたらすみません。

    キャンセル

  • 2017/10/15 23:28

    ご返信ありがとうございます。とんでもございません。
    恐らくまさにそこが不明点なポイントです。ご提示いただいたコードでfunction adding () 内において1)の生成と2)の設定はOKで
    1) var elm_add = document.createElement('button');で生成してから
    2) elm_add.addEventListener("click", warnings, false);その要素にイベン

    私のコードのように、addingの外で
    elm_2.addEventListener("click", warnings, false);
    としてイベントを登録することはどちらも設定対象の要素が存在しているように見えるので不思議に感じてました。

    こちらこそ、的違いな発想であれば本当に申し訳ございません。

    キャンセル

  • 2017/10/15 23:45

    今回の場合adding関数はid属性に`btn_1`が設定されたボタンがクリックされるまで実行されません。
    質問者さんのコードでは`var elm_2 = document.getElementById("hoge");`が実行される前にボタンがクリックされていない場合id属性にhogeが設定された要素は存在しないことになりますので、その直後にあるイベントの登録処理はエラーとなります。
    回答文のコードの場合は設定対象の要素が存在する状態でイベントの登録を行っているのでエラーにはなりません。

    キャンセル

  • 2017/10/16 00:59

    ご回答ありがとうございます。
    なるほど、イベント(クリック)が起こるタイミングとその時の要素の状況を適切に把握していなければならないのですね。今回で言えば、一度クリックを押して処理の実行が開始されても、その時点はid="hoge"の要素が存在しないということですか。。
    大変よくわかりました!
    改めて深謝を申し上げます。

    キャンセル

+2

もし2つの<script>にコードを分ける必要がないのなら、elm_addを作った時にその場でaddEventListenerすればいいですよ。

    function adding() {
      var elm_add = document.createElement('button');
      elm_add.id = "hoge";
      elm_add.textContent = 'btn added';
      elm_add.addEventListener("click", warnings);  // <--
      var objBody = document.getElementsByTagName("body").item(0);
      objBody.appendChild(elm_add);
    }

    var elm = document.getElementById("btn_1");
    elm.addEventListener("click", adding);

    function warnings() {
      alert('it works! congraturations!!')
    }

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/10/15 23:30

    ご回答ありがとうございます。
    やはり、初めのイベント設定(adding)の中に、新たに追加した要素のイベントを設定すると、追加イベントを認識して動作するのですね。。。不思議です。

    キャンセル

  • 2017/10/15 23:59

    あ、すみません。s8_chuさんの回答と一緒というかそちらのほうがいいですね。失礼しました。

    質問文のコードだと、
    var elm_2 = document.getElementById("hoge");
    elm.addEventListener("click", adding, false);
    がページが読み込まれるタイミングで実行されます。
    しかしまだ#hogeは存在していません。(ボタン#btn_1を押していないので)
    よって elm_2 に null が入ったためにそのエラーが出たんです。

    キャンセル

  • 2017/10/16 01:00

    コメントありがとうございます。
    みなさんのおかげで現状、問題点、解決方法がよくわかりました。
    本当に勉強になりました。
    御礼申し上げます。

    キャンセル

+1

下記例はクラスですが、それ以外でも基本的に考え方は同じです。

【jQueryを使わずjavascriptだけで書き直した際の記法メモ - Qiita】
https://qiita.com/moriyaman/items/3b3f7878f8ecc2b76372

document.addEventListener('click', function (e) {
  if (e.target.className ==='hoge') {
    // function
  } 
});

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/10/15 23:00

    コメントありがとうございます。
    以下のコードで動作は確認できました。
    qiitaの記事を読んだのですが、すみません、現在の私では理解ができませんでした。上のs8_chu様にもご質問させていただいたのですが、
    動的に生成した要素は、document.getElementByIdでは捕まえることができず、イベントオブジェクトから要素を特定して処理をさせなければならないのでしょうか。
    ・どちらもdocumentオブジェクトから処理しているのにgetElementbyIdからは要素を特定できずイベントオブジェクトからであれば特定できる違いがわかりませんでした。。
    ・また、本件んでいうクラストはどの点を指しているのでしょうか、、どちらもクラスやnewしたインスタンス等がないとお見受けしたため、理解することができませんでした。。

    ご回答をいただいたのにもかかわらず追加の質問でご迷惑をおかけしていることは承知しております。もし、厚かましければご放念いただいて結構ですが、もし可能であれば少しだけヒントを頂けると幸甚です。
    よろしくお願い申し上げます。

    <button id="btn_1">btn</button>
    <script type="text/javascript">
    function adding() {
    var elm_add = document.createElement('button');
    elm_add.id = "hoge";
    elm_add.textContent='btn added';
    var objBody = document.getElementsByTagName("body").item(0);
    objBody.appendChild(elm_add);
    }
    var elm = document.getElementById("btn_1");
    elm.addEventListener("click", adding, false);

    </script>
    <script type="text/javascript">
    // var elm_2 = document.getElementById("hoge");
    document.addEventListener("click", function(e){
    console.log(e);
    if (e.target.id==='hoge') {
    alert('it works! congraturations!!')
    }
    });
    </script>
    </body>

    キャンセル

  • 2017/10/15 23:16 編集

    > ・どちらもdocumentオブジェクトから処理しているのにgetElementbyIdからは要素を特定できずイベントオブジェクトからであれば特定できる違いがわかりませんでした。。
    getElementbyIdで取得できなかった要素(後から追加される要素)にイベントをつけられないということがわからない、ということですか?
    (ここから追記)コードは書かれた場所で即実行されます。そのときに無い要素は取得できません。(ここまで追記)

    > どちらもクラスやnewしたインスタンス等がないとお見受けしたため、理解することができませんでした。。
    「e.target.className ==='hoge'」CSSにも「クラス」があります。それのことです。

    >(コード)
    https://jsfiddle.net/w6q1o3xw/
    動いていませんか?

    キャンセル

  • 2017/10/15 23:38

    コメント誠にありがとうございます。
    またわかりづらくて申し訳ございませんが、ご指摘のコードに基づき、記載したコードで動作自体は無事に確認することができました。

    1) なるほど、document.getElementById('hoge')を即時実行した時点ではまだ、その要素が存在しないため、
    Uncaught TypeError: Cannot read property 'addEventListener' of null
    として要素を見つけることができないとうことですね。
    しかしながら、イベントオブジェクトから特定する場合には、ここではmouseeventでclickに基づき、新たにdocumentをloadして動的に生成された#hogeを識別し追加でイベントが設定できるというように理解いたしました。

    2) オブジェクト指向上のクラスではなく.class class=""という属性のクラスのことでしたか。。失礼いたしました。

    お付き合いを頂きましたことに深く御礼を申し上げます。

    キャンセル

  • 2017/10/15 23:45

    「新たにdocumentをloadして」は何を指しているのでしょうか。どのコードについて書かれていますか?
    もし「document.createElement」について書かれているとしたら、「新たにdocumentをloadして」ではなく「新たに要素を作成することで」くらいが妥当かと思います。少なくとも「load」という動作ではないと思います。

    キャンセル

  • 2017/10/16 01:06

    確かにloadは不適切でした。mouceclickのたびにイベントオブジェクトを呼び出してその時の状況を監視できるので、動的に生成された要素も監視できると解釈しました。
    素人のような言い回しで申し訳ございませんが、なぜ一度のクリックでまだ生成されていない要素を拾うことができるのかが初めは不思議でしょうがなかったのですが、他の方のアプローチと異なり、このようにイベントオブジェクトから都度情報を得て、拾うことができるのだととても勉強になりました!
    夜遅くまでありがとうございます。
    teratailにも感謝です♬よろしくお願い申し上げます。

    キャンセル

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

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

関連した質問

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

  • JavaScript

    13873questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。