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

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

詳細はこちら
Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

foreach

foreachは、List・Collection・Arrayといったデータ構造の各要素に対して繰り返し処理を実行するために扱われる、制御構造の構文です。

JavaScript

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

Q&A

2回答

1761閲覧

JavaScriptでforEach文が機能しない

moto12

総合スコア15

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

foreach

foreachは、List・Collection・Arrayといったデータ構造の各要素に対して繰り返し処理を実行するために扱われる、制御構造の構文です。

JavaScript

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

0グッド

0クリップ

投稿2020/12/19 09:19

編集2020/12/19 10:51

前提・実現したいこと

JavaSciriptのsetAttributeとremoveAttributeを用いて、
ある要素をクリックする度に、他の要素を出現したり、消えたりさせたい。
(1−1をクリックすれば、1−1のメンバーのみが表示されるようにしたい。現在、どこをクリックしても全てのクラスのメンバーが出現する。)

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

イメージ説明

エラーメッセージ Uncaught TypeError: members[i].removeAtrribute is not a function at HTMLSpanElement.<anonymous> (new:97)

該当のソースコード

JavaScript

1...省略 2 3 <div class="grade-class"> 4 <span class="class-num1">1−1</span> 5 <div class="members"> 6 <%= f.collection_check_boxes :user_ids, User.where(grade:1, class_number:1).all.order("student_number ASC"), :id, :name %> 7 </div> 8 9 <span class="class-num1">1−2</span> 10 <div class="members"> 11 <%= f.collection_check_boxes :user_ids, User.where(grade:1, class_number:2).all.order("student_number ASC"), :id, :name %> 12 </div> 13 14...省略 15 16<script> 17 const c1 = document.querySelectorAll('.class-num1'); 18 const members = document.querySelectorAll('.members'); 19 20 c1.forEach(function(list) { 21 list.addEventListener('click', function(){ 22 const members = document.querySelectorAll('.members'); 23 for(const member of members) {) { 24 if (member.getAttribute('style') == 'display:block;') { 25 member.removeAttribute('style','display:block;') 26 } else { 27 member.setAttribute('style','display:block;') 28 } 29 } 30 }) 31 }) 32</script> 33

試したこと

ここに問題に対して試したことを記載してください。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答2

0

NodeListのようなArrayっぽいオブジェクトをArrayとして扱いたいのであれば、
Array.fromを使うのがいいです。
今回のケースで言えば、こんな感じです。

Javascript

1Array.from(c1).forEach(function(list) 2{ 3 ... 4}

※追記
NodeListでもforEachは有効でしたね。失礼しました。

これだけでは何なので、改めて回答します。
質問のコードでは下記の点が問題になります。
1.style属性の書き換えが両方ともdisplay:blockになっている。
2.要素毎に表示/非表示の判別を行っていない。
3.要素から次の兄弟要素を取得するなら、nextElementSiblingで一発。
これを踏まえまして、こんな感じで。

const c1 = document.querySelectorAll('.class-num1'); c1.forEach(function(list) { list.addEventListener('click', function() { c1.forEach(function(node) { this.nextElementSibling.setAttribute("style", node == this ? "display:block" : "display:none" ); },this); }); });

余談ですが、表示/非表示を切り替えるなら、style属性を直接書き換えるのではなく、cssで非表示のクラスを作って、classListのadd,remove,toggleで対応するのが楽でいいです。

css

1.hide{display:none}

Javascript

1targetElement.classList.add("hide"); //非表示 2targetElement.classList.remove("hide");//表示 3targetElement.classList.toggle("hide");//切り替え

投稿2020/12/20 11:28

編集2020/12/20 12:14
AT_2nd

総合スコア266

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

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

0

document.querySelectorAll('.members') で返ってくるのは配列ではなくオブジェクトです。試しに F12 を押してコンソールで typeof document.querySelectorAll('div')とすると良いでしょう。

で、オブジェクトの length というのは信用なりません。なぜかというと値以外にメソッドの数なんかもカウントされてしまうからです。ではどうするか。幸いにして返ってくるオブジェクトは iterable なオブジェクト ですので

JavaScript

1for(let i = 0; i < members.length; i++) { 2 ...

の代わりに

JavaScript

1for(const member of members) { 2 ....

を使ってみてください。

追記:
Rails について調べることになり非常に悔しいのですが、Rails の where 関数は複数の引数を取れないようです。それならそれでエラー出せって話なんですが……。詳細は以下をお読みください。
【Rails】find・find_by・whereについてまとめてみた - Qiita

Ruby

1User.where(grade:1, class_number:1)

Ruby

1User.where(grade:1).where(class_number:1)

に変えるとよいのではないでしょうか。

JavaScript にもまだ問題があるかと思いましたが、なんとか動きそうではありました。ですがより操作を楽にしたいならば

HTML

1 <span class="class-num1">1−1</span> 2 <div> 3 <div class="members"> 4 <%= f.collection_check_boxes :user_ids, User.where(grade:1, class_number:1).all.order("student_number ASC"), :id, :name %> 5 </div> 6 </div>

とネストを一段深くすることも検討してみてください。class 名も変えてあげると見通しが良くなるでしょう。

投稿2020/12/19 09:33

編集2020/12/19 11:18
A_kirisaki

総合スコア2853

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

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

moto12

2020/12/19 10:49

ご返答ありがとうございます!! for(const member of members) { に代えてみたのですが、 やはり1−1をクリックしても1−1と1−2のメンバーが出現します... 他に見るべき箇所はありますか...?
A_kirisaki

2020/12/19 10:59

あ、これ思ったより面倒なやつだ。追記しますのでお待ちくださいね
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問