Evaluate list.contains string in JSTL

88

Ich muss ein Element ausblenden, wenn bestimmte Werte in der JSP vorhanden sind

Die Werte werden in einer Liste gespeichert, also habe ich versucht:

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

Aber es funktioniert nicht.

Wie kann ich bewerten, ob eine Liste einen Wert in JSTL enthält? Die Liste und die Werte sind Zeichenfolgen.

OscarRyz
quelle
17
Beachten Sie, dass die angegebene Syntax seit EL 2.2 (das als Teil von Servlet 3.0 / JSP 2.2, das im Dezember 2009 veröffentlicht wurde) bereitgestellt wird, wie beabsichtigt funktioniert.
BalusC

Antworten:

69

Leider denke ich, dass JSTL nichts anderes als eine Iteration durch alle Elemente unterstützt, um dies herauszufinden. In der Vergangenheit habe ich die forEach-Methode in der Core-Tag-Bibliothek verwendet:

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

Nachdem dies ausgeführt wurde, ist $ {enthält} gleich "wahr", wenn myList myValue enthält.

Kaleb Brasee
quelle
10
funktioniert gut, wenn die Liste klein ist. Stellen Sie nur fest, dass dies auf diese Weise Leistungskosten verursacht.
Chii
Ja, es würde geben, wenn Sie hoch genug werden. Ich habe es für Sammlungen von 10 bis 20 Dingen verwendet und keine Leistungsprobleme festgestellt. Was ich für schlimmer halte, ist die Anzahl der Zeilen von JSTL. Dennoch denke ich, dass dies der einzige Weg ist, ohne eine eigene TLD einzurichten (was nicht allzu schwierig ist und sich durchaus lohnen kann).
Kaleb Brasee
97

Es gibt keine integrierte Funktion, um dies zu überprüfen. Sie würden lediglich eine eigene tld-Funktion schreiben, die eine Liste und ein Element verwendet und die Methode includes () der Liste aufruft. z.B

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

Erstellen Sie dann eine Klasse mit dem Namen Yourclass und fügen Sie eine statische Methode mit dem Namen includes mit der obigen Signatur hinzu. Ich bin sicher, dass die Implementierung dieser Methode ziemlich selbsterklärend ist:

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

Dann können Sie es in Ihrem jsp verwenden:

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

Das Tag kann von jeder JSP auf der Site verwendet werden.

edit: mehr info zur tld datei - mehr info hier

Chii
quelle
4
Ich empfehle, Collectionstatt Listin der Taglib zu verwenden - es funktioniert genauso, unterstützt aber mehr Sammlungstypen wie Sets
Ralph
28

Eine andere Möglichkeit, dies zu tun, ist die Verwendung eines Map (HashMap)Paares mit Schlüssel und Wert, das Ihr Objekt darstellt.

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

In JSTL

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

Dies sollte true zurückgeben, wenn das Paar in der Karte vorhanden ist

Tamersalama
quelle
2
Dies ist auch meine bevorzugte Methode. Richten Sie im Ansichtsmodell Hashmaps für alles ein, was ich in einer Ansicht benötige. Sie lassen sich gut in die EL-Syntax integrieren und sind bei der Suche blitzschnell.
Boris B.
Nur noch eine Sache: Wenn ein Schlüssel vorhanden ist, der Wert jedoch null oder leer ist, wird false zurückgegeben.
Zai
1
Oder wenn die Karte Boolesche Werte enthält , test="${isPresentByValue[myValue]}".
Noumenon
14

Sie müssen die Funktion fn:contains()oder fn:containsIgnoreCase()verwenden.

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

oder

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

Hinweis: Dies funktioniert wie folgt.mylist.toString().contains("apple")Wenn dies nicht der Fall ist, verwenden Sie einen anderen Ansatz.

tk_
quelle
2
Dies ist nicht der richtige Ansatz. Es wird sich im Grunde so verhalten, wie mylist.toString().contains("apple")es absolut nicht das ist, was Sie anfänglich erwarten würden.
BalusC
ohh .. ja das ist nicht was ich erwarte. Auf jeden Fall werde ich meine Antwort mit dieser Geldstrafe aktualisieren.
tk_
2

Das Folgende ist eher eine Problemumgehung als eine Antwort auf Ihre Frage, aber möglicherweise ist es das, wonach Sie suchen. Wenn Sie Ihre Werte in eine Karte anstelle einer Liste einfügen können, ist Ihr Problem dadurch gelöst. Ordnen Sie Ihre Werte einfach einem Wert ungleich Null zu und tun Sie dies, <c:if test="${mymap.myValue ne null}">style='display:none;'</c:if>oder Sie können sie sogar zuordnen style='display:none;und einfach ausgeben${mymap.myValue}

Svachon
quelle
Ich denke, die Syntax sollte <c: if test = "$ {mymap [myValue] ne null}"> style = 'display: none;' </ c: if> Andernfalls wird die Variable "myValue" nicht ausgewertet.
Andreas
2
${fn:contains({1,2,4,8}, 2)}

ODER

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

Wenn Sie EL 3.0+ verwenden , ist der beste Ansatz in diesem Fall, wie diese andere Antwort in einem anderen Thema erläutert wird:

Für eine Collectiones einfach ist, sondern nur die Verwendung Colleciton#contains() Methode in 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>

Für ein Object[](Array) benötigen Sie mindestens EL 3.0 und nutzen die neue Lambda-Unterstützung.

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

Wenn Sie noch nicht mit EL 3.0 arbeiten, müssen Sie eine benutzerdefinierte EL-Funktion erstellen. [...]

Lucas Basquerotto
quelle
-1

Wenn Sie Spring Framework verwenden, können Sie Spring TagLib und SpEL verwenden:

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

Ich fand diese Lösung erstaunlich.

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

Die Ausgabe für den obigen Code lautet

Meine Liste ist [eins, zwei, drei]

Meine Liste enthält zwei

Meine Liste enthält:

Ich hoffe es hilft jemandem.

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

Das funktioniert gut für mich.

Vladislav
quelle
18
Dies führt die Überprüfung durch, nachdem beide Elemente in einen String konvertiert wurden. Die Liste wird in eine Zeichenfolge konvertiert und nicht auf Elementbasis überprüft. Wenn task.subscribers eine Liste ["eins", "zwei", "einundzwanzig"] ist, lautet sie: wahr für Kunde = "eins" (zweimal übereinstimmend) falsch für Kunde = "drei" (keine Übereinstimmung) wahr für Kunde = "zwanzig" (was nicht das ist, wonach Sie suchen)
Ricardo Marimon
2
Diese Antwort war sich der Warnung des Rmarimon bewusst und entsprach genau meinem Anwendungsfall.
CodeReaper