2009-09-29 5 views
73

muszę ukryć element, jeśli niektóre wartości są obecne w JSPOcenić list.contains łańcuch w JSTL

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 robi nie działa.

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

+13

Należy zauważyć, że podane składnia działa jako odnie od EL 2.2 (która jest wniesiona jako część Servlet 3.0/JSP 2.2, który został wydany gru 2009). – BalusC

+0

możliwy duplikat [zestawów i list JSTL - sprawdzanie, czy element istnieje w zestawie] (http://stackoverflow.com/questions/1076679/jstl-sets-and-lists-checking-if-item-exists-in-a -set) –

Odpowiedz

58

Niestety, myślę, że JSTL nie obsługuje niczego oprócz iteracji przez wszystkie elementy, aby to zrozumieć. W przeszłości Użyłem metody foreach w tagu biblioteki rdzenia:

<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 biegnie to $ {} zawiera będzie równa „true”, jeśli myList zawarte myValue.

+8

działa ładnie, jeśli lista jest mała. Po prostu zdaj sobie sprawę, że jest to koszt wydajności, aby to zrobić w ten sposób. – Chii

+0

Tak, byłby, gdybyś był wystarczająco wysoki. Używałem go do kolekcjonowania 10-20 rzeczy i nie doświadczyłem żadnych problemów z wydajnością. Uważam, że gorsza jest liczba linii JSTL. Mimo to uważam, że jest to jedyny sposób bez ustanowienia własnej TLD (która nie jest zbyt trudna i może być tego warta). –

92

nie ma wbudowanej funkcji, aby to sprawdzić - należy napisać własną funkcję Tld, która pobiera listę i element, i wywołuje metodę contains() 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 statyczną metodę nazwaną zawierającą powyższy podpis. I jestem pewien, że wdrożenie tej metody jest dość oczywista:

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żna użyć go w jsp:

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

Znacznik może być używany z dowolnym JSP w miejscu.

edit: więcej informacji dotyczących pliku tld - more info here

+0

: - S Gdzie znajduje się ten kod? Wygląda groźnie – OscarRyz

+1

Edytował odpowiedź z nieco więcej informacji. – Chii

+4

Polecam użyć 'Collection' zamiast' List' w taglib - działa tak samo, ale obsługuje więcej typów kolekcji, takich jak 'Set's – Ralph

2

Poniżej jest raczej obejście niż odpowiedź na swoje pytanie, ale może być to, czego szukasz. Jeśli umieścisz swoje wartości na mapie zamiast na liście, rozwiąże to Twój problem. Wystarczy mapować wartości do wartości zerowej, a nie to <c:if test="${mymap.myValue ne null}">style='display:none;'</c:if> zrobić lub można nawet map do style='display:none; i po prostu wyjście ${mymap.myValue}

+0

Myślę, że składnia powinna być style = 'display: none;' W przeciwnym razie zmienna "myValue" nie jest oceniana. – Andreas

25

Innym sposobem na osiągnięcie tego jest użycie Map (HashMap) z kluczem, napięcie par reprezentujących swó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]}"> 

ten powinien powrócić true, jeśli para istnieć na mapie

+2

To jest mój preferowany sposób, ustaw hashmaps w viewmodel na wszystko, czego potrzebuję w widoku. Integrują ładnie ze składnią EL i podczas wyszukiwania są błyskawicznie szybkie. –

+0

Jeszcze jedna rzecz, jeśli klucz istnieje, ale wartość jest pusta lub pusta, to zwróci false. – Zai

+1

Lub jeśli mapa zawiera wartości logiczne, 'test =" $ {isPresentByValue [myValue]} "'. – Noumenon

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

Działa to dobrze dla mnie.

+15

Sprawdza się 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 jest listą ["jeden", "dwa", "twentyone"] to będzie: prawda dla klienta = "jeden" (dopasowanie dwa razy) fałsz dla klienta = "trzy" (bez pasujących) prawda dla klienta = "dwadzieścia" (co nie jest tym, czego szukasz) – rmarimon

+1

Znając ostrzeżenie rmarimona, ta odpowiedź pasuje do mojego dokładnego przypadku użycia. – CodeReaper

-1

Jeśli używasz Spring Framework, można użyć Wiosna 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> 
-1

trzeba 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> 
+0

@BalusC 1) Nie ma żadnych ograniczeń dotyczących odpowiedzi na pytania dotyczące SOF. 2) Proszę pomyśleć przed głosowaniem, ta odpowiedź jest poprawna i przetestowałem to przed udzieleniem odpowiedzi. Zaktualizowałem odpowiedź, aby była jeszcze bardziej przejrzysta. – tkr

+0

@BalusC Nie powtarzam, a ja po prostu udzielam odpowiedzi rozszerzonej. Nie chcę też podawać łyżki lektorowi. Myślę, że o to właśnie chodzi. W SO nadal możemy odpowiedzieć na pytanie, czy istnieje akceptowana odpowiedź, czy nie. Czy to nie jest dla ciebie seansem? A także szanuję głosowanie w dół, ponieważ rozumiem, że każda osoba, która ma ponad 100 przedstawicieli, może to zrobić. Więc jeśli chcesz zamknąć odpowiedź uprzejmie, otwórz głos. – tkr