Avalie list.contains string em JSTL

88

Eu preciso esconder um elemento se certos valores estiverem presentes no JSP

Os valores são armazenados em uma lista, então tentei:

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

Mas não funciona.

Como posso avaliar se uma lista contém um valor em JSTL, a lista e os valores são strings.

OscarRyz
fonte
17
Observe que a sintaxe fornecida funciona conforme planejado desde EL 2.2 (que é trazido como parte do Servlet 3.0 / JSP 2.2 que foi lançado em dezembro de 2009).
BalusC de

Respostas:

69

Infelizmente, acho que o JSTL não oferece suporte a nada além de uma iteração por meio de todos os elementos para descobrir isso. No passado, usei o método forEach na biblioteca de tags principais:

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

Após a execução, $ {contains} será igual a "true" se myList contiver myValue.

Kaleb Brasee
fonte
10
funciona bem se a lista for pequena. Basta perceber que há um custo de desempenho para fazer isso dessa maneira.
Chii,
Sim, haveria se você subir o suficiente. Eu usei para coleções de 10-20 coisas e não tive nenhum problema de desempenho. O que acho pior é o número de linhas do JSTL. Ainda assim, acho que essa é a única maneira de não configurar seu próprio TLD (o que não é muito difícil e pode muito bem valer a pena).
Kaleb Brasee
97

não há nenhum recurso embutido para verificar isso - o que você faria é escrever sua própria função tld, que pega uma lista e um item, e chama o método contains () da lista. por exemplo

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

Em seguida, crie uma classe chamada Yourclass e adicione um método estático chamado contains com a assinatura acima. Tenho certeza de que a implementação desse método é bastante autoexplicativa:

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

Depois, você pode usá-lo em seu jsp:

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

A tag pode ser usada em qualquer JSP no site.

editar: mais informações sobre o arquivo tld - mais informações aqui

Chii
fonte
4
Eu recomendo usar em Collectionvez de Listno taglib - funciona da mesma forma, mas suporta mais tipos de coleção como Sets
Ralph
28

Outra maneira de fazer isso é usar um Map (HashMap)com pares de chave e valor que representam seu objeto.

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

Em JSTL

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

Isso deve retornar verdadeiro se o par existir no mapa

tamersalama
fonte
2
Esta também é minha maneira preferida de configurar hashmaps no modelo de visualização para tudo o que preciso em uma visualização. Eles se integram perfeitamente à sintaxe EL e são extremamente rápidos na pesquisa.
Boris B.
Só mais uma coisa, se a chave existir, mas o valor for nulo ou vazio, ele retornará falso.
Zai
1
Ou se o mapa contém booleanos test="${isPresentByValue[myValue]}",.
Noumenon
14

Você precisa usar a função fn:contains()ou 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>

ou

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

Nota: Isso funcionará comomylist.toString().contains("apple")e se não for o que você está procurando, use uma outra abordagem.

tk_
fonte
2
Esta não é a abordagem correta. Basicamente, ele se comportará como algo mylist.toString().contains("apple")absolutamente diferente do que você esperava inicialmente.
BalusC
ohh .. sim, isso não é o que eu esperava. De qualquer forma, atualizarei minha resposta com esta autuação.
tk_
2

O que segue é mais uma solução alternativa do que uma resposta à sua pergunta, mas pode ser o que você está procurando. Se você pudesse colocar seus valores em um mapa em vez de uma lista, isso resolveria seu problema. Basta mapear seus valores para um valor não nulo e fazer isso <c:if test="${mymap.myValue ne null}">style='display:none;'</c:if>ou você pode até mesmo mapear style='display:none;e simplesmente gerar${mymap.myValue}

Svachon
fonte
Acho que a sintaxe deve ser <c: if test = "$ {mymap [myValue] ne null}"> style = 'display: none;' </ c: if> Caso contrário, a variável "myValue" não será avaliada.
Andreas
2
${fn:contains({1,2,4,8}, 2)}

OU

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

Se você estiver usando EL 3.0+ , a melhor abordagem neste caso é como esta outra resposta explicada em outro tópico:

Para Collectionfacilitar, basta usar o Colleciton#contains() método em 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>

Para um Object[](array), você precisa de no mínimo EL 3.0 e utiliza seu novo suporte para 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 você ainda não estiver no EL 3.0, precisará criar uma função EL personalizada. [...]

Lucas basquerotto
fonte
-1

Se estiver usando Spring Framework, você pode usar 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>
xxg
fonte
-1

Eu achei essa solução incrível.

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

A saída para o código acima é

Minha lista é [um, dois, três]

Minha lista contém dois

Minha lista contém,

Eu espero que isso ajude alguém.

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

Este trabalho é bom para mim.

Vladislav
fonte
18
Isso faz a verificação após converter os dois elementos em string. A lista é convertida em uma string e não é verificada por elemento. Se task.subscribers for uma lista ["um", "dois", "vinte e um"], será: verdadeiro para o cliente = "um" (correspondendo duas vezes) falso para o cliente = "três" (sem correspondência) verdadeiro para o cliente = "vinte" (que não é o que você está procurando)
Ricardo Marimon
2
Estando ciente do aviso do rmarimon, essa resposta correspondeu ao meu caso de uso exato.
CodeReaper