Oceń list.contains string w JSTL

89

Muszę ukryć element, jeśli na stronie JSP obecne są określone wartości

Wartości są przechowywane na liście, więc próbowałem:

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

Ale to nie działa.

Jak mogę ocenić, czy lista zawiera wartość w JSTL, lista i wartości są ciągami.

OscarRyz
źródło
17
Zauważ, że podana składnia działa zgodnie z zamierzeniami od wersji EL 2.2 (która jest częścią Servlet 3.0 / JSP 2.2 wydanego w grudniu 2009).
BalusC,

Odpowiedzi:

70

Niestety, myślę, że JSTL nie obsługuje niczego poza iteracją przez wszystkie elementy, aby to zrozumieć. W przeszłości korzystałem z metody forEach w podstawowej bibliotece tagów:

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

Po uruchomieniu $ {zawiera} będzie równe „true”, jeśli mojaLista zawiera myValue.

Kaleb Brasee
źródło
10
działa dobrze, jeśli lista jest niewielka. Po prostu uświadom sobie, że zrobienie tego w ten sposób wiąże się z kosztami wydajności.
Chii,
Tak, byłoby, gdybyś dostatecznie wysoko. Użyłem go do kolekcji 10-20 rzeczy i nie doświadczyłem żadnych problemów z wydajnością. Myślę, że gorsza jest liczba linii JSTL. Mimo to myślę, że jest to jedyny sposób bez zakładania własnego TLD (co nie jest zbyt trudne i może być tego warte).
Kaleb Brasee
97

nie ma wbudowanej funkcji, która by to sprawdzała - co byś zrobił, to napisanie własnej funkcji tld, która pobiera listę i element i wywołuje metodę include () listy. na przykład

//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>

Następnie utwórz klasę o nazwie Yourclass i dodaj metodę statyczną o nazwie zawiera z powyższym podpisem. Jestem pewien, że implementacja tej metody nie wymaga wyjaśnień:

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);
   }
}

Następnie możesz użyć go w swoim jsp:

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

Znacznika można używać z dowolnej strony JSP w serwisie.

edycja: więcej informacji o pliku tld - więcej informacji tutaj

Chii
źródło
4
Polecam używać Collectionzamiast Listw taglib - działa tak samo, ale obsługuje więcej typów kolekcji, takich jak Sets
Ralph
28

Innym sposobem na to jest użycie Map (HashMap)par z kluczem i wartością reprezentujących twój obiekt.

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

W JSTL

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

Powinno to zwrócić prawdę, jeśli para istnieje na mapie

tamersalama
źródło
2
Jest to również mój ulubiony sposób, ustaw hashmaps w modelu widoku dla wszystkiego, czego potrzebuję w widoku. Ładnie integrują się ze składnią EL i działają błyskawicznie podczas wyszukiwania.
Boris B.
Jeszcze jedna rzecz, jeśli klucz istnieje, ale wartość jest null lub pusta, zwróci false.
Zai
1
Lub jeżeli mapa posiada wartości logicznych, test="${isPresentByValue[myValue]}".
Noumenon
15

Musisz użyć funkcji fn:contains()lub 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>

lub

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

Uwaga: to zadziała,mylist.toString().contains("apple")a jeśli nie jest to to, czego szukasz, lepiej użyj innego podejścia.

tk_
źródło
2
To nie jest właściwe podejście. Zasadniczo zachowuje się tak, jak mylist.toString().contains("apple")absolutnie nie jest to, czego początkowo można by się spodziewać.
BalusC
ohh .. tak nie tego oczekuję. W każdym razie zaktualizuję moją odpowiedź o tę karę.
tk_
2

Poniżej przedstawiono bardziej obejście niż odpowiedź na Twoje pytanie, ale może to być to, czego szukasz. Jeśli możesz umieścić swoje wartości na mapie zamiast na liście, rozwiązałoby to problem. Po prostu zmapuj swoje wartości na wartość inną niż null i zrób to <c:if test="${mymap.myValue ne null}">style='display:none;'</c:if>lub możesz nawet odwzorować style='display:none;i po prostu wyprowadzić${mymap.myValue}

svachon
źródło
Myślę, że składnia powinna wyglądać następująco: <c: if test = "$ {mymap [myValue] ne null}"> style = 'display: none;' </ c: if> W przeciwnym razie zmienna "myValue" nie jest oceniana.
Andreas
2
${fn:contains({1,2,4,8}, 2)}

LUB

  <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>
Tony Hung
źródło
0

Jeśli używasz EL 3.0+ , najlepszym podejściem w tym przypadku jest taka, jak ta inna odpowiedź wyjaśniona w innym temacie:

Aby było Collectionto łatwe, po prostu użyj Colleciton#contains() metody w 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>

W przypadku Object[](tablicy) potrzebujesz co najmniej EL 3.0 i wykorzystaj jego nową obsługę 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>

Jeśli jeszcze nie korzystasz z EL 3.0, musisz utworzyć niestandardową funkcję EL. […]

Lucas Basquerotto
źródło
-1

Jeśli używasz Spring Framework, możesz użyć Spring TagLib i 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>
xxg
źródło
-1

To rozwiązanie wydało mi się niesamowite.

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

Dane wyjściowe dla powyższego kodu to

Moja lista to [jeden, dwa, trzy]

Moja lista zawiera dwa

Moja lista zawiera,

Mam nadzieję, że to komuś pomoże.

oOXAam
źródło
-2
<c:if test="${fn:contains(task.subscribers, customer)}">

U mnie to działa dobrze.

Vladislav
źródło
18
To jest sprawdzanie po konwersji obu elementów na łańcuch. Lista jest konwertowana na ciąg znaków i nie jest sprawdzana dla każdego elementu. Jeśli task.subscribers to lista ["jeden", "dwa", "dwadzieścia jeden"], to będzie: prawda dla klienta = "jeden" (dopasowanie dwa razy) fałsz dla klienta = "trzy" (brak dopasowania) prawda dla klienta = „dwadzieścia” (nie jest tym, czego szukasz)
Ricardo Marimon
2
Będąc świadomym ostrzeżenia rmarimona, ta odpowiedź pasowała dokładnie do mojego przypadku użycia.
CodeReaper,