web-dev-qa-db-ja.com

Thymeleaf#lists.contains()式ユーティリティが機能しない

Thymeleaf標準方言を使用して、チェックボックスのリストをフォームにレンダリングしようとしています。レンダリングは問題ありませんが、問題は、thymeleaf#lists.contains()式ユーティリティメソッドを使用して「checked」プロパティをチェックボックスに適用しようとするところです。

したがって、次のフィールドを持つモデルクラスがあります。

private List<Template> templates;

@FormParam("selectedTemplates")
private List<String> selectedTemplates = Lists.newArrayList();

Thymeleafテンプレートのhtmlフラグメント:

<div th:each="template : *{templates}">
    <input type="checkbox" name="selectedTemplates" th:value="${template.id}" 
    th:checked="${#lists.contains(product.selectedTemplates, template.id)}" />
    <label th:text="${template.filename} + ' (' + ${template.description} + ')'" />
    <!-- Attempt to use the list contains to check the field -->
    <div th:text="${product.selectedTemplates}"/>
    <div th:text="${template.id}"/>  
    <div th:text="${#lists.contains(product.selectedTemplates, template.id)}" />
</div>

選択する必要のあるチェックボックスの1つに対するページの出力。

<input type="checkbox" name="selectedTemplates" value="4" /> (Template Name)
<div>[4,5]</div>
<div>4</div>
<div>false<div>

ご覧のとおり、値[4,5]のリストを出力し、#lists.containsメソッドを使用して、template.idが含まれているかどうかを確認しますが、このメソッドは常にfalseを返します。メソッドをテストするためにハードコードされたIDをいくつか試しましたが、常に「false」が返されます。

例えば:

<div th:text="${product.selectedTemplates}"/>
<div th:text="${#lists.contains(product.selectedTemplates, 4)}" />

[4,5] falseを出力します

<div th:text="${product.selectedTemplates}"/>
<div th:text="${#lists.contains(product.selectedTemplates, '4')}" />

[4,5] falseを出力します

私が何を間違っているのかわかりませんが、それはとても簡単なようで、他に何を試すべきかわかりません。私の推測では、構文に何か問題があります。どんな提案やアドバイスも大歓迎です。この問題のトラブルシューティングに関するリソースを見つけることができません。thymeleafガイドはそのセクションをすばやく説明しています。

8
Tom Lerma

私はthymeleafフォーラムでこの回答を提示し、根本的な原因と解決策を特定するための助けを得ました。 [ http://forum.thymeleaf.org/Problem-with-thymeleaf-expression-utility-lists-contains-td4027317.html] [1] を参照してください

基本的に、単一文字列はデフォルトで文字タイプとして解釈されるため、リスト内のどの文字列とも一致しません。複数文字の文字列は文字列型に評価されるため、期待どおりに機能します。検索対象の値をhtmlでエンコードされた引用符でカプセル化することにより、パーサーは1文字の文字列をchar型ではなく文字列型として評価するように強制されます。例えば:

<div th:text="${#lists.contains(testList, &quot;3&quot;)}"/>
<div th:text="${#lists.contains(testList, &quot;P&quot;)}"/>

誰かが根本的な原因と解決策に興味を持った場合に備えて、これを投稿したかっただけです。

17
Tom Lerma

質問が古いことは知っていますが、この回答を投稿しているので、同じ問題を抱えている他のユーザーにも役立ちます。

あなたなのか他のユーザーなのかわかりませんが ここ 追加する必要があることがわかりました

'' + template.id

そう:

th:checked="${#lists.contains(product.selectedTemplates, '' + template.id)}" 

私にとってはうまくいきました!ありがとうございました

6
SaganTheBest

さらに実験を行ったところ、#lists.contains()ユーティリティメソッドが単一の文字列に対して機能しないという問題が見つかりました。 thymeleaf 2.0.19を使用していることを付け加えますが、2.1.1.RELEASEも試したところ同じ結果になりました。

モデルに簡単なリストを作成し、いくつかの値を追加しました。

@FormParam("testList") 
private List<String> testList = Lists.newArrayList(); 

testList.add("test1"); 
testList.add("test2"); 
testList.add("3"); 
testList.add("P"); 
testList.add("33");

次に、次のように#lists.contains()メソッドをテストしました。

<div th:text="${product.testList}"/>
<div th:text="${#lists.contains(product.testList, 'test1')}"/>
<div th:text="${#lists.contains(product.testList, 'test2')}"/>
<div th:text="${#lists.contains(product.testList, '3')}"/>
<div th:text="${#lists.contains(product.testList, 'P')}"/>
<div th:text="${#lists.contains(product.testList, '33')}"/>

そして、出力は次のとおりです。

<div>[test1, test2, 3, P, 33]</div>
<div>true</div>
<div>true</div>
<div>false</div>
<div>false</div>
<div>true</div>

したがって、このメソッドは1文字の文字列では機能しないことは明らかです。私は新しいプロジェクトに取り組んでいるので、これらのIDを駆動するシーケンスをリセットするだけで、使用する単一の文字IDがなくなります。それは確かに私が望んでいた解決策ではありませんが、それは機能します。また、質問のコンテキストでメソッドを機能させるために、次のようにIDに空の文字を追加する必要があったことも追加します。

th:checked="${#lists.contains(product.selectedTemplates, '' + template.id)}"

これがないと、template.idはLong型であるため、containsメソッドは「false」を返します。

2
Tom Lerma

ご覧のとおり、選択したテンプレートにはIDではなくテンプレートのリストが含まれています。

その場合は、次のようなリストを確認する必要があります。

<input type="checkbox" name="selectedTemplates" th:value="${template.id}" th:checked="${#lists.contains(product.selectedTemplates, template)}" />
0
Martin Frey