Оцінити list.contens містить рядок у JSTL


89

Мені потрібно приховати елемент, якщо певні значення присутні в JSP

Ці значення зберігаються у списку, тому я спробував:

<c:if test="${  mylist.contains( myValue ) }">style='display:none;'</c:if>

Але це не працює.

Як я можу оцінити, якщо список містить значення в JSTL, список і значення є рядками.


17
Зауважте, що наведений синтаксис працює належним чином з EL 2.2 (який подається як частина Servlet 3.0 / JSP 2.2, випущеної в грудні 2009 р.).
BalusC

Відповіді:


70

На жаль, я думаю, що JSTL не підтримує нічого, крім ітерації всіх елементів, щоб це зрозуміти. Раніше я використовував метод forEach у бібліотеці основних тегів:

<c:set var="contains" value="false" />
<c:forEach var="item" items="${myList}">
  <c:if test="${item eq myValue}">
    <c:set var="contains" value="true" />
  </c:if>
</c:forEach>

Після цього $ {contains} буде дорівнює "true", якщо myList містив myValue.


10
працює добре, якщо список невеликий. Просто усвідомлюйте, що робити це таким чином вистачає продуктивності.
Chii

Так, це було б, якщо ви станете досить високим. Я використовував його для колекцій з 10-20 речей і не мав жодних проблем із продуктивністю. Річ, на мою думку, гірша - це кількість рядків JSTL. Тим не менш, я думаю, що це єдиний спосіб без створення власного TLD (що не надто складно і цілком може того вартувати).
Kaleb Brasee

97

немає вбудованої функції, щоб це перевірити - що ви зробите, це напишіть власну функцію tld, яка бере список і елемент і викликає метод list's ((). напр

//in your own WEB-INF/custom-functions.tld file add this
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib
        PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
        "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib
        xmlns="http://java.sun.com/xml/ns/j2ee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
        version="2.0"
        >
    <tlib-version>1.0</tlib-version>
    <function>
        <name>contains</name>
        <function-class>com.Yourclass</function-class>
        <function-signature>boolean contains(java.util.List,java.lang.Object)
        </function-signature>
    </function>
</taglib>

Потім створіть клас, який називається Yourclass, і додайте статичний метод, що називається contains, із зазначеним вище підписом. Я впевнений, що реалізація цього методу досить зрозуміла:

package com; // just to illustrate how to represent the package in the tld
public class Yourclass {
   public static boolean contains(List list, Object o) {
      return list.contains(o);
   }
}

Тоді ви можете використовувати його у своєму jsp:

<%@ taglib uri="/WEB-INF/custom-functions.tld" prefix="fn" %>
<c:if test="${  fn:contains( mylist, myValue ) }">style='display:none;'</c:if>

Тег можна використовувати з будь-якого JSP на сайті.

редагувати: більше інформації щодо файлу tld - докладніше тут


4
Я рекомендую використовувати Collectionзамість Listу taglib - він працює однаково, але підтримує більше типів колекцій, таких як Sets
Ralph

28

Інший спосіб зробити це - використання Map (HashMap)пар з Key, Value, що представляють ваш об’єкт.

Map<Long, Object> map = new HashMap<Long, Object>();
map.put(new Long(1), "one");
map.put(new Long(2), "two");

У JSTL

<c:if test="${not empty map[1]}">

Це має повернути true, якщо пара існує на карті


2
Це теж мій улюблений спосіб, налаштуйте хеш-карти в viewmodel для всього, що мені знадобиться у поданні. Вони чудово інтегруються з синтаксисом EL і блискавично працюють під час пошуку.
Борис Б.

Ще одна річ, якщо ключ існує, але значення є нульовим або порожнім, тоді воно поверне false.
Zai

1
Або , якщо карта має булеві, test="${isPresentByValue[myValue]}".
Noumenon

15

Вам потрібно використовувати функцію fn:contains()або fn:containsIgnoreCase().

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>

...

 <c:if test="${not fn:containsIgnoreCase(mylist, 'apple')}">
        <p>Doesn't contain 'apple'</p>
    </c:if>

або

<c:if test="${not fn:contains(mylist, 'Apple')}">
            <p>Contains 'Apple'</p>
        </c:if>

Примітка: Це спрацює як,mylist.toString().contains("apple")і якщо це не те, що ви шукаєте, краще застосуйте інший підхід.


2
Це не правильний підхід. В основному він буде поводитися так, mylist.toString().contains("apple")що абсолютно не те, що ви спочатку очікували.
BalusC

ох ... так, це не те, що я очікую. У будь-якому разі я оновлю свою відповідь цим штрафом.
tk_

2

Далі подано більше обхідного шляху, ніж відповіді на ваше запитання, але це може бути саме те, що ви шукаєте. Якщо ви можете помістити свої значення на карту, а не в список, це вирішить вашу проблему. Просто зіставіть свої значення з ненульовим значенням і зробіть це, <c:if test="${mymap.myValue ne null}">style='display:none;'</c:if>або ви навіть можете зіставити style='display:none;і просто вивести${mymap.myValue}


Я думаю, синтаксис повинен бути <c: if test = "$ {mymap [myValue] ne null}"> style = 'display: none;' </ c: if> В іншому випадку змінна "myValue" не обчислюється.
Андреас,

2
${fn:contains({1,2,4,8}, 2)}

АБО

  <c:if test = "${fn:contains(theString, 'test')}">
     <p>Found test string<p>
  </c:if>

  <c:if test = "${fn:contains(theString, 'TEST')}">
     <p>Found TEST string<p>
  </c:if>

0

Якщо ви використовуєте EL 3.0+ , найкращий підхід у цьому випадку полягає в тому, як ця інша відповідь пояснюється в іншій темі:

Для Collectionцього це просто, просто скористайтеся Colleciton#contains() методом у EL.

<h:panelGroup id="p1" rendered="#{bean.panels.contains('p1')}">...</h:panelGroup>
<h:panelGroup id="p2" rendered="#{bean.panels.contains('p2')}">...</h:panelGroup>
<h:panelGroup id="p3" rendered="#{bean.panels.contains('p3')}">...</h:panelGroup>

Для Object[](масиву) вам знадобиться принаймні EL 3.0 і скористайтеся його новою підтримкою Lambda.

<h:panelGroup id="p1" rendered="#{bean.panels.stream().anyMatch(v -> v == 'p1').get()}">...</h:panelGroup>
<h:panelGroup id="p2" rendered="#{bean.panels.stream().anyMatch(v -> v == 'p2').get()}">...</h:panelGroup>
<h:panelGroup id="p3" rendered="#{bean.panels.stream().anyMatch(v -> v == 'p3').get()}">...</h:panelGroup>

Якщо ви ще не користуєтесь EL 3.0, вам потрібно буде створити власну функцію EL. [...]


-1

Якщо ви використовуєте Spring Framework, ви можете використовувати Spring TagLib та SpEL:

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
---
<spring:eval var="containsValue" expression="mylist.contains(myValue)" />
<c:if test="${containsValue}">style='display:none;'</c:if>

-1

Я знайшов це рішення дивовижним.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%
   ArrayList list = new ArrayList();
   list.add("one");
   list.add("two");
   list.add("three");
%>
<c:set var="list" value="<%=list%>" />
<html>
<body>
        My list is ${list}<br/>
<c:if test='${fn:contains(list, "two")}'>
        My list contains two <br/>
</c:if>
<c:if test='${fn:contains(list, ",")}'>
        My list contains , 
</c:if>
</body>
</html>

Результатом для наведеного вище коду є

Мій список: [один, два, три]

Мій список містить два

Мій список містить,

Сподіваюся, це комусь допоможе.


-2
<c:if test="${fn:contains(task.subscribers, customer)}">

Для мене це чудово працює.


18
Це робить перевірку після перетворення обох елементів у рядок. Список перетворюється на рядок і не перевіряється на основі кожного елемента. Якщо task.subscribers - це список ["один", "два", "двадцять один"], це буде: true для замовника = "один" (збігається двічі) false для замовника = "три" (не збігається) true для замовника = "двадцять" (що не те, що ви шукаєте)
Рікардо Марімон

2
Знаючи про попередження римаримона, ця відповідь відповідала моєму точному варіанту використання.
CodeReaper
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.