Оценить список. Содержит строку в JSTL

Мне нужно скрыть элемент, если в JSP присутствуют определенные значения

Значения хранятся в списке, поэтому я попробовал:

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

Но это не работает.

Как я могу оценить, содержит ли список значение в JSTL, если список и значения являются строками.


person OscarRyz    schedule 29.09.2009    source источник
comment
Обратите внимание, что данный синтаксис работает так, как задумано, начиная с EL 2.2 (который входит в состав Servlet 3.0 / JSP 2.2, выпущенного в декабре 2009 г.).   -  person BalusC    schedule 10.01.2012
comment
возможный дубликат наборов и списков JSTL - проверка, если элемент существует в наборе   -  person Matt Ball    schedule 18.06.2012


Ответы (10)


К сожалению, я думаю, что 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.

person Kaleb Brasee    schedule 29.09.2009
comment
хорошо работает, если список невелик. Просто поймите, что такой способ требует высокой производительности. - person Chii; 29.09.2009
comment
Да, было бы, если бы ты достаточно высоко поднялся. Я использовал его для коллекций из 10-20 вещей и не испытывал никаких проблем с производительностью. Что еще хуже, так это количество строк JSTL. Тем не менее, я думаю, что это единственный способ без создания собственного TLD (что не так уж сложно и вполне может того стоить). - person Kaleb Brasee; 29.09.2009

встроенной функции для проверки нет - вам нужно написать собственную функцию tld, которая принимает список и элемент и вызывает метод списка contains (). например

//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
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);
   }
}
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-файле - подробнее здесь < / а>

person Chii    schedule 29.09.2009
comment
Я рекомендую использовать Collection вместо List в taglib - он работает так же, но поддерживает больше типов коллекций, таких как Sets - person Ralph; 16.12.2015

Другой способ сделать это - использовать Map (HashMap) с парами ключ, значение, представляющими ваш объект.

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]}">

Это должно вернуть истину, если пара существует на карте

person tamersalama    schedule 07.09.2010
comment
Это мой предпочтительный способ - настроить хэш-карты в модели просмотра для всего, что мне нужно в представлении. Они прекрасно интегрируются с синтаксисом EL и молниеносны при поиске. - person Boris B.; 03.08.2012
comment
Еще одна вещь: если ключ существует, но значение равно нулю или пусто, он вернет false. - person Zai; 09.05.2014
comment
Или, если карта содержит логические значения, test="${isPresentByValue[myValue]}". - person Noumenon; 07.02.2017

Вам необходимо использовать _1 _ или 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>

or

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

Примечание. Это будет работать как mylist.toString().contains("apple"), и если это не то, что вы ищете, лучше использовать другой подход.

person tk_    schedule 30.11.2017
comment
Это неправильный подход. По сути, он будет вести себя как mylist.toString().contains("apple"), что совершенно не соответствует вашим ожиданиям. - person BalusC; 04.11.2019
comment
ох .. да это не то, что я ожидал. В любом случае я дополню свой ответ этим штрафом. - person tk_; 05.11.2019

Следующее - это скорее обходной путь, чем ответ на ваш вопрос, но, возможно, это именно то, что вы ищете. Если вы можете поместить свои значения на карту вместо списка, это решит вашу проблему. Просто сопоставьте свои значения с ненулевым значением и сделайте это <c:if test="${mymap.myValue ne null}">style='display:none;'</c:if>, или вы даже можете сопоставить их с style='display:none; и просто вывести ${mymap.myValue}

person svachon    schedule 08.10.2009
comment
Я предполагаю, что синтаксис должен быть ‹c: if test = $ {mymap [myValue] ne null}› style = 'display: none;' ‹/ c: if› В противном случае переменная myValue не оценивается. - person Andreas; 08.06.2010

Если вы используете 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. [...]

person Lucas Basquerotto    schedule 03.02.2020

вы не должны использовать fn: contains (), потому что это сравнение строк. Итак, предположим, что ваш список содержит 11,12,13 и вы написали fn: contains (list, '1'), это даст вам «истинный» результат. Но я надеюсь, что вы ожидаете false, поскольку 1 нет в списке. Вы должны создать свой собственный тег для использования list.contains (Object o).

person Hitesh Pant    schedule 05.05.2021

Если вы используете 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>
person xxg    schedule 20.07.2017

Я нашел это решение потрясающим.

<%@ 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>

Вывод для приведенного выше кода:

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

В моем списке два

Мой список содержит,

Надеюсь, это кому-то поможет.

person oOXAam    schedule 03.11.2019

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

У меня это отлично работает.

person Vladislav    schedule 26.10.2013
comment
Это проверка после преобразования обоих элементов в строку. Список преобразуется в строку и не проверяется для отдельных элементов. Если task.subscribers - это список [один, два, двадцать один], он будет: true для customer = one (совпадение дважды) false для customer = three (нет совпадений) true для customer = 20 (это не то, что вы ищете) - person Ricardo Marimon; 10.11.2013
comment
Зная о предупреждении Рмаримона, этот ответ точно соответствовал моему варианту использования. - person CodeReaper; 08.10.2014