67833

[code]

    <div class="file" id="fileList">
        <div th:each="file : ${list}" class="file-list">
            <img src="/images/example.png">
            <div class="text">
                <p th:text="P1"></p>
                <p th:text="P2"></p>
                <p th:text="P3"></p>
                <p th:text="P4"></p>
                <p th:text="'Status:' + ${file.status}" id="pTag"></p>
            </div>
       </div>
    </div>
    
[/code]

上記のようなHTMLがあります。fileの中にPタグが５つあり、それを１セットとして、そのセットをコレクション(list)の数だけ描画しています。  
この時、５つ目のPタグの値を同じページ内の別のタグ内で使いたいのです。その時にJSで

[code]

    var tmp = document.getElementById("pTag");
    
[/code]

とすれば ${file.status} の値を取ってはこれるのですが、コレクションの最初の１つだけしか取れないのです。  
th:each="file : ${list}" としているので、listの数が２つ以上ある時はその数だけpTagも取得したいのです。

ちなみに

[code]

    var listObj = document.getElementById("fileList");
    console.log(listObj);
    
[/code]

とすればログを開いた時にlistObjの中にちゃんと個数分の ${file.status} を見ることができています。  
ですが、listObjはiterableなオブジェクトではないらしくループ処理をかけて取得するというようなことはできませんでした。

何か良い方法ご存知ないですか？


CC BY-SA 4.0
2020-06-19T01:01:32.767
67797
2020-06-20T11:50:04.227
2020-06-20T11:50:04.227
9515
35503
question
javascript html thymeleaf
HTMLでth:each属性の中身をコレクションの個数分だけ取得するには


ひとつ確認しますが、ページ内に `<div class="file-list">...</div>`
のかたまりがコレクションの数だけ繰り返されるという理解でよいですよね？ それとも、上記のHTMLの構造を全く変えずに`<p>`
の5個セットだけが複製されるという意図でしょうか。ここでは前者だと仮定してお答えします。

ID はページ内で重複してはいけないので、 `getElementById()`
では1つしか要素を得ることができないのです。以下にいくつか考えられる方針を挙げます。

(A) 5つ目の `p` 要素に同じクラス名を割り当てて、
[`document.getElementsByClassName()`](https://developer.mozilla.org/ja/docs/Web/API/Document/getElementsByClassName)
でクラスが指定されたすべての要素を得る。この関数で返ってくるのは iterable **ではない**
[`HTMLCollection`](https://developer.mozilla.org/ja/docs/Web/API/HTMLCollection)
型のDOMオブジェクトです。ループのしかたは下の補足に書いてあります。

(B) 指定したCSSセレクターにマッチした全ての要素を返す
[`document.querySelectorAll()`](https://developer.mozilla.org/ja/docs/Web/API/Document/querySelectorAll)
を使って、（やや技巧的ですが） `document.querySelectorAll("div.text > p:nth-child(5)")`
のようにする。こちらで返ってくるのは
[`NodeList`](https://developer.mozilla.org/ja/docs/Web/API/NodeList)
型のDOMオブジェクトで、こちらは `HTMLCollection` と違って iterable なので `for...of` ループを使うことができます。

(C) DOMツリーを自力でたどる。 `document.getElementById("fileList").children` が
`HTMLCollection` 型のDOMオブジェクトです。これを下に示すやりかたでループします。

私のおすすめとしては「5個セット」というルールが将来変わっても壊れないように、(A) でクラス名を指定するやり方が優れていると思います。

* * *

### （補足） HTMLCollection のループのしかた

`HTMLCollection` は実体としては要素のリストなのですが iterable ではないので、 `for...of`
ループで列挙することができません。`.length` プロパティとインデックスアクセス `[i]`
は使えるので、インデックスで列挙することもできますが、インデックスを経由したくなければ以下のように `Array` に変換してループするのが簡単です。

[code]

    let fileList = document.getElementById("fileList");
    // fileList.children は HTMLCollection
    for (let child of Array.from(fileList.children)) {
        // child は div#fileList の子要素
    }
    
[/code]


CC BY-SA 4.0
2020-06-20T09:49:31.037
67833
2020-06-20T09:49:31.037
40595
67797
answer