Valuta list.contains stringa in JSTL


89

Devo nascondere un elemento se determinati valori sono presenti nel JSP

I valori sono memorizzati in un elenco, quindi ho provato:

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

Ma non funziona.

Come posso valutare se una lista contiene un valore in JSTL, la lista ei valori sono stringhe.


17
Si noti che la sintassi data funziona come previsto a partire da EL 2.2 (introdotto come parte di Servlet 3.0 / JSP 2.2 rilasciato a dicembre 2009).
BalusC

Risposte:


70

Purtroppo, penso che JSTL non supporti nient'altro che un'iterazione attraverso tutti gli elementi per capirlo. In passato, ho utilizzato il metodo forEach nella libreria di tag principale:

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

Dopo l'esecuzione, $ {contains} sarà uguale a "true" se myList conteneva myValue.


10
funziona bene se l'elenco è piccolo. Renditi conto che c'è un costo in termini di prestazioni per farlo in questo modo.
Chii

Sì, ci sarebbe se ti sballassi abbastanza. L'ho usato per raccolte di 10-20 cose e non ho riscontrato problemi di prestazioni. La cosa che penso sia peggio è il numero di righe di JSTL. Tuttavia, penso che questo sia l'unico modo senza impostare il tuo TLD (il che non è troppo difficile e potrebbe valerne la pena).
Kaleb Brasee,

98

non esiste una funzionalità incorporata per verificarlo: quello che faresti è scrivere la tua funzione tld che accetta una lista e un elemento e chiama il metodo contiene () della lista. per esempio

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

Quindi crea una classe chiamata Yourclass e aggiungi un metodo statico chiamato contiene con la firma sopra. Sono sicuro che l'implementazione di quel metodo è abbastanza autoesplicativa:

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

Quindi puoi usarlo nel tuo jsp:

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

Il tag può essere utilizzato da qualsiasi JSP nel sito.

modifica: maggiori informazioni sul file tld - maggiori informazioni qui


4
Consiglio di usarlo al Collectionposto del Listtaglib - funziona allo stesso modo ma supporta più tipi di raccolta come Sets
Ralph

28

Un altro modo per farlo è usare una Map (HashMap)coppia chiave con valore che rappresenta il tuo oggetto.

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]}">

Questo dovrebbe restituire vero se la coppia esiste nella mappa


2
Questo è anche il mio modo preferito, imposta hashmap nel viewmodel per tutto ciò di cui ho bisogno in una vista. Si integrano perfettamente con la sintassi EL e sono velocissimi durante la ricerca.
Boris B.

Ancora una cosa, se la chiave esiste ma il valore è nullo o vuoto, restituirà false.
Zai

1
Oppure, se la mappa contiene booleani, test="${isPresentByValue[myValue]}".
Noumenon

15

È necessario utilizzare la funzione fn:contains()o 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>

o

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

Nota: questo funzioneràmylist.toString().contains("apple")e se questo non è ciò che stai cercando, usa un altro approccio.


2
Questo non è l'approccio corretto. Fondamentalmente si comporterà come mylist.toString().contains("apple")non è assolutamente quello che ti aspetteresti inizialmente.
BalusC

ohh .. sì questo non è quello che mi aspetto. Ad ogni modo aggiornerò la mia risposta con questa sanzione.
tk_

2

Quanto segue è più una soluzione alternativa che una risposta alla tua domanda, ma potrebbe essere quello che stai cercando. Se puoi mettere i tuoi valori in una mappa invece che in un elenco, questo risolverebbe il tuo problema. Mappa semplicemente i tuoi valori su un valore non nullo e fallo <c:if test="${mymap.myValue ne null}">style='display:none;'</c:if>o puoi anche mappare style='display:none;e semplicemente output${mymap.myValue}


Immagino che la sintassi dovrebbe essere <c: if test = "$ {mymap [myValue] ne null}"> style = 'display: none;' </ c: if> Altrimenti la variabile "myValue" non viene valutata.
Andreas

2
${fn:contains({1,2,4,8}, 2)}

O

  <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

Se stai usando EL 3.0+ , l'approccio migliore in questo caso è come questa altra risposta spiegata in un altro argomento:

Per una Collectioncosa semplice, usa il Colleciton#contains() metodo 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>

Per un Object[](array), avresti bisogno di un minimo di EL 3.0 e utilizzerai il suo nuovo supporto 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>

Se non sei ancora su EL 3.0, devi creare una funzione EL personalizzata. [...]


-1

Se stai usando Spring Framework, puoi usare Spring TagLib e 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

Ho trovato questa soluzione fantastica.

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

L'output per il codice sopra è

La mia lista è [uno, due, tre]

La mia lista ne contiene due

La mia lista contiene,

Spero che aiuti qualcuno.


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

Questo funziona bene per me.


18
Questo sta facendo il controllo dopo aver convertito entrambi gli elementi in stringa. L'elenco viene convertito in una stringa e non controllato in base agli elementi. Se task.subscribers è un elenco ["uno", "due", "ventuno"] sarà: true per cliente = "uno" (corrispondenza due volte) false per cliente = "tre" (nessuna corrispondenza) vero per cliente = "venti" (che non è quello che stai cercando)
Ricardo Marimon

2
Essendo a conoscenza dell'avvertimento del rmarimon, questa risposta corrispondeva al mio esatto caso d'uso.
CodeReaper
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.