haruka4434
@haruka4434

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

askama、jinjaのテンプレートエンジンのforループで生成された分のHTMLをJSのfor文で繰り返し処理できるようにする

解決したいこと

askama、jinjaのテンプレートエンジンのforループで生成(表示)された分だけのHTMLのテキストコンテンツと、それとは別で生成(表示)されるテキストコンテンツをJavaScriptのfor文を使って照らし合わせて、一致しているものはそのまま表示し、一致していないものは表示しないようにする方法を教えてください。

該当するソースコード

これでdivタグがデータべースに元々ある値の数だけ表示されます。

{% for entry in entries %}
<div>
    (このdivタグが量産される)
</div>
{% endfor %}

例: データベースに3個の値があった場合。

{% for entry in entries %}
<div>
    <p>hogehoge</p>
</div>
<div>
    <p>hogehoge</p>
</div>
<div>
    <p>hogehoge</p>
</div>
{% endfor %}

このdivタグのテキストコンテンツと別でJSを使って自動生成される

タグのテキストコンテンツを一つ一つ照らし合わせて、値が同じであればそのまま表示し、違っていれば表示しないようにしたいと考えています。

{% for entry in entries %}
<div>
    <p>hogehoge</p>
</div>
<div>
    <p>HUGEHUGE</p>
    <!-- これは値が異なっているので表示しない。 -->
</div>
<div>
    <p>hogehoge</p>
</div>
{% endfor %}

<p id="other_content">hogehoge</P> <!-- JSを使ってid指定でテキストコンテンツを埋め込んだ<p>タグと比較する -->
0

3Answer

ベタですが...
比較対象のpタグにclass="db_val"を付与して以下のJavaScriptを追記

qiita.js
var other_content = document.getElementById('other_content').innerHTML;
var arr = document.getElementsByClassName('db_val');

for(var i = 0; i < arr.length; i++){
	if(arr[i].innerHTML != other_content){
		arr[i].style.display = 'none';
	}
}
0Like

Comments

  1. @haruka4434

    Questioner

    @hzxq様のコードを実行するとarrがclass指定なので、lengthは取れるのですが、中のテキストコンテンツが取れず、undefinedになり正常に比較することができませんでした。
    なので実行すると本来は表示されるはずの要素まで、すべて消えてしまいました。

    なのでarrをid指定に切り替えてみると、中のテキストコンテンツは取れるのですが、lengthが取れずにundefinedになりました。なのでdivタグにclass="node_count"をつけてノードの数を数えるためのdivを作り、JSのコードを下記のとおりに書き換えて実行すると、


    ```JavaScript
    var other_content = document.getElementById("other_content").textContent;
    var arr = document.getElementById("db_val"); //NEW class指定からid指定に変更
    var node_count = document.getElementsByClassName("node_count"); //NEW ノードを数える変数を追加

    for (var i = 0; i < node_count.length; i++) { //NEW node_countでループするように変更
    if (arr[i].textContent != other_content) {
    arr[i].style.display = "none";
    }
    }
    ```

    「Uncaught (in promise) TypeError: arr[i] is undefined」
    とエラーが出ました。

「Uncaught (in promise) TypeError: arr[i] is undefined」
とエラーが出ました。

Document.getElementById() → 単一のElementオブジェクトを返す。
Document.getElementsByClassName() → 複数のElementオブジェクトを返す(≒配列)

このことから、getElementByIdで取得した単一のElementオブジェクトに対して
配列の添字を記述しているので、「arr[i] は 配列じゃないよ~(配列として定義されていないよ~)」というエラーになっています。

本題の動作しない件ですが、
(推測になりますが)上記の内容が混在してしまい、プロパティの指定に多少混乱が生じている可能性があります。

JavaScriptにコメントを記述しましたので再度ご確認ください。
※質問者様のコードを考慮し、innerHTMLプロパティはtextContentプロパティへ変更しています。

qiita.html
{% for entry in entries %}
<div>
    <p class="db_val">hogehoge</p>
</div>
<div>
    <p class="db_val">HUGEHUGE</p>
    <!-- これは値が異なっているので表示しない。 -->
</div>
<div>
    <p class="db_val">hogehoge</p>
</div>
{% endfor %}

<p id="other_content">hogehoge</p>

<script>
// id="other_content" が付与された要素のテキストを取得して other_content に格納
var other_content = document.getElementById('other_content').textContent;

// class="db_val" が付与された要素を全て取得して 配列arr に格納
var arr = document.getElementsByClassName('db_val');

// 配列arrの要素を1つずつ確認する。
for(var i = 0; i < arr.length; i++){
    // arrのi番目の要素のテキストと、other_content が不一致かを判定
    if(arr[i].textContent != other_content){
        // 不一致であれば、配列arrのi番目の要素を非表示にする。
        arr[i].style.display = 'none';
    }
}
</script>

私で良ければ是非解決までお手伝いさせて頂ければと思います。
再度エラーが発生した場合は気兼ねなくお尋ねください。

0Like

@hzxq様のアドバイスのおかげで無事コードを動かすことができました。

最終的にいくつかのクラス名と変数名、それに合わせてコードを変更しました。
divタグごと消したかったので、pタグについていたクラスをdivタグに移しました。

qiita.html
{% for entry in entries %}
<div class="elements_group">
	<p>hogehoge</p>
</div>
<div class="elements_group">
	<p>HUGEHUGE</p>
</div>
<div class="elements_group">
	<p>hogehoge</p>
</div>
{% endfor %}

<p id="key_content">hogehoge</p>

<script>
	const keyContent = document.getElementById("key_content").textContent;
	const elementsGroup = document.getElementsByClassName("elements_group");

	for (let i = 0; i < elementsGroup.length; i++) {
		if (elementsGroup.item(i).children[0].textContent.trim() != keyContent) {
			elementsGroup[i].style.display = "none";
		}
	}
</script>

ご丁寧に説明いただき、誠にありがとうございました。

0Like

Your answer might help someone💌