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.


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.


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


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


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.


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}


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>

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. [...]


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

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


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

Das funktioniert gut für mich.


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.