Оцінити 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.