🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
JavaScript

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

Q&A

解決済

3回答

8657閲覧

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

SugiuraY

総合スコア318

JavaScript

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

0グッド

6クリップ

投稿2017/10/15 12:58

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

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

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

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

HTML

1<body> 2 3<button id="btn_1">btn</button> 4 5 <script type="text/javascript"> 6 function adding() { 7 var elm_add = document.createElement('button'); 8 elm_add.id = "hoge"; 9 elm_add.textContent='btn added'; 10 var objBody = document.getElementsByTagName("body").item(0); 11 objBody.appendChild(elm_add); 12 } 13 var elm = document.getElementById("btn_1"); 14 elm.addEventListener("click", adding, false); 15 16 </script> 17 18 <script type="text/javascript"> 19 20 function warnings (){ 21 alert('it works! congraturations!!') 22 } 23 24 25 var elm_2 = document.getElementById("hoge"); 26 elm_2.addEventListener("click", warnings, false); 27 //Uncaught TypeError: Cannot read property 'addEventListener' of null 28 </script> 29</body>

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

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

HTML

1<html lang="ja"> 2<head> 3 <meta charset="UTF-8"> 4 <title>タイトル</title> 5</head> 6<body> 7<button id="btn_1">btn</button> 8<script> 9 var num = 0; 10 11 function adding() { 12 var elm_add = document.createElement('button'); 13 elm_add.id = "hoge" + num; 14 elm_add.textContent = 'btn added'; 15 var objBody = document.getElementsByTagName("body").item(0); 16 objBody.appendChild(elm_add); 17 elm_add.addEventListener("click", warnings, false); 18 num++; 19 } 20 21 var elm = document.getElementById("btn_1"); 22 elm.addEventListener("click", adding, false); 23 24 function warnings() { 25 alert('it works! congraturations!!') 26 } 27</script> 28</body> 29</html>

投稿2017/10/15 13:11

s8_chu

総合スコア14731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SugiuraY

2017/10/15 13:31

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

2017/10/15 13:39

> JavaScriptの処理の順番を考えた場合には、動的な要素の生成にまたaddEventListnerを設定することと、最初のイベント処理内(adding)でこれを設定することに大きな違いが無いように感じます。 少し意味が分からないので、もし良ければもう少し詳しく何が分からないか教えていただけませんか?
SugiuraY

2017/10/15 13:52

コメントありとうございます。抽象的で申し訳ございません。 1) #btn_1のbutton要素をクリックすると動的に#hoge button要素を生成するイベントが発生 2) #hoge button要素をクリックするとalert("it works!....")を表示するイベントが発生 という順番かと思います。私のコードとご提示いただいたの違いは2)を外に出すか、1)の中のコールバック(イベント)関数に含めるかの違いかと思います。なぜその違いでJavascriptは#hoge button要素の認識するかしないかの違いが生じるのかがその構造または処理の過程が私のわからない点になります。 そもそも動的に生成した要素はそれ以下のコードでgetElementByIdしても捕まえることができないのは、イベントバブリングと関連があるのでしょうか。。 一方例えば、下記のkei344様のように、生成した後の要素は捕まえることができないとしてdocumentオブジェクトから改めて全体を読み込みイベントオブジェクトから改めて特定の要素を取得して処理を記載するという点はなんとなく直感的に理解はできるのですが、、、 初心者の質問にお付き合いいただき、誠に申し訳ございませんが 何卒、よろしくお願い申し上げます。
s8_chu

2017/10/15 14:14

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

2017/10/15 14: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); としてイベントを登録することはどちらも設定対象の要素が存在しているように見えるので不思議に感じてました。 こちらこそ、的違いな発想であれば本当に申し訳ございません。
s8_chu

2017/10/15 14:45

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

2017/10/15 15:59

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

0

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

lang

1 function adding() { 2 var elm_add = document.createElement('button'); 3 elm_add.id = "hoge"; 4 elm_add.textContent = 'btn added'; 5 elm_add.addEventListener("click", warnings); // <-- 6 var objBody = document.getElementsByTagName("body").item(0); 7 objBody.appendChild(elm_add); 8 } 9 10 var elm = document.getElementById("btn_1"); 11 elm.addEventListener("click", adding); 12 13 function warnings() { 14 alert('it works! congraturations!!') 15 }

投稿2017/10/15 13:30

karamarimo

総合スコア2555

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SugiuraY

2017/10/15 14:30

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

2017/10/15 14:59

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

2017/10/15 16:00

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

0

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

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

JavaScript

1document.addEventListener('click', function (e) { 2 if (e.target.className ==='hoge') { 3 // function 4 } 5});

投稿2017/10/15 13:09

編集2017/10/15 13:10
kei344

総合スコア69596

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SugiuraY

2017/10/15 14: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>
kei344

2017/10/15 14:16 編集

> ・どちらもdocumentオブジェクトから処理しているのにgetElementbyIdからは要素を特定できずイベントオブジェクトからであれば特定できる違いがわかりませんでした。。 getElementbyIdで取得できなかった要素(後から追加される要素)にイベントをつけられないということがわからない、ということですか? (ここから追記)コードは書かれた場所で即実行されます。そのときに無い要素は取得できません。(ここまで追記) > どちらもクラスやnewしたインスタンス等がないとお見受けしたため、理解することができませんでした。。 「e.target.className ==='hoge'」CSSにも「クラス」があります。それのことです。 >(コード) https://jsfiddle.net/w6q1o3xw/ 動いていませんか?
SugiuraY

2017/10/15 14:38

コメント誠にありがとうございます。 またわかりづらくて申し訳ございませんが、ご指摘のコードに基づき、記載したコードで動作自体は無事に確認することができました。 1) なるほど、document.getElementById('hoge')を即時実行した時点ではまだ、その要素が存在しないため、 Uncaught TypeError: Cannot read property 'addEventListener' of null として要素を見つけることができないとうことですね。 しかしながら、イベントオブジェクトから特定する場合には、ここではmouseeventでclickに基づき、新たにdocumentをloadして動的に生成された#hogeを識別し追加でイベントが設定できるというように理解いたしました。 2) オブジェクト指向上のクラスではなく.class class=""という属性のクラスのことでしたか。。失礼いたしました。 お付き合いを頂きましたことに深く御礼を申し上げます。
kei344

2017/10/15 14:45

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

2017/10/15 16:06

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問