Evaluasi list.contains string dalam JSTL

89

Saya perlu menyembunyikan elemen jika nilai tertentu ada di JSP

Nilai disimpan dalam Daftar jadi saya mencoba:

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

Tapi, itu tidak berhasil.

Bagaimana saya bisa mengevaluasi jika daftar berisi nilai dalam JSTL, daftar dan nilai adalah string.

OscarRyz
sumber
17
Perhatikan bahwa sintaks yang diberikan berfungsi sebagaimana mestinya sejak EL 2.2 (yang dibawa sebagai bagian dari Servlet 3.0 / JSP 2.2 yang dirilis pada Desember 2009).
BalusC

Jawaban:

70

Sayangnya, saya pikir JSTL tidak mendukung apa pun kecuali iterasi melalui semua elemen untuk mencari tahu. Dulu, saya telah menggunakan metode forEach di pustaka tag inti:

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

Setelah ini berjalan, $ {contains} akan sama dengan "true" jika myList berisi myValue.

Kaleb Brasee
sumber
10
berfungsi dengan baik jika daftarnya kecil. Sadarilah bahwa ada biaya kinerja untuk melakukannya dengan cara ini.
Chii
Ya, akan ada jika Anda merasa cukup tinggi. Saya telah menggunakannya untuk koleksi 10-20 hal dan tidak mengalami masalah kinerja apa pun. Hal yang menurut saya lebih buruk adalah jumlah baris JSTL. Namun, saya pikir ini adalah satu-satunya cara tanpa menyiapkan TLD Anda sendiri (yang tidak terlalu sulit dan mungkin sangat berharga).
Kaleb Brasee
97

tidak ada fitur bawaan untuk memeriksanya - yang akan Anda lakukan adalah menulis fungsi tld Anda sendiri yang mengambil daftar dan item, dan memanggil metode berisi () daftar. misalnya

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

Kemudian buat kelas yang disebut KelasAnda, dan tambahkan metode statis yang disebut berisi dengan tanda tangan di atas. Saya yakin penerapan metode itu cukup jelas:

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

Kemudian Anda dapat menggunakannya di jsp Anda:

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

Tag dapat digunakan dari JSP mana pun di situs.

edit: info lebih lanjut tentang file tld - info lebih lanjut di sini

Chii
sumber
4
Saya merekomendasikan untuk menggunakan Collectionalih-alih Listdi taglib - ini berfungsi sama tetapi mendukung lebih banyak jenis koleksi seperti Sets
Ralph
28

Cara lain untuk melakukan ini adalah menggunakan a Map (HashMap)with Key, pasangan Nilai yang mewakili objek Anda.

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

Di JSTL

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

Ini harus mengembalikan nilai true jika pasangan ada di peta

tamersalama.dll
sumber
2
Ini juga cara yang saya sukai, atur hashmaps di viewmodel untuk semua yang saya perlukan dalam tampilan. Mereka terintegrasi dengan baik dengan sintaks EL dan secepat kilat saat menelusuri.
Boris B.
Satu hal lagi, jika kunci ada tetapi nilainya null atau kosong maka itu akan mengembalikan false.
Zai
1
Atau jika Peta berisi boolean test="${isPresentByValue[myValue]}",.
Noumenon
15

Anda perlu menggunakan fungsi fn:contains()atau 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>

atau

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

Catatan: Ini akan bekerja sepertimylist.toString().contains("apple")dan jika ini bukan yang Anda cari, lebih baik gunakan pendekatan lain.

tk_
sumber
2
Ini bukanlah pendekatan yang benar. Ini pada dasarnya akan berperilaku seperti mylist.toString().contains("apple")yang sama sekali tidak seperti yang Anda harapkan pada awalnya.
BalusC
ohh .. ya ini bukan yang saya harapkan. Pokoknya saya akan mengupdate jawaban saya dengan denda ini.
tk_
2

Berikut ini lebih merupakan solusi daripada jawaban atas pertanyaan Anda tetapi mungkin itu yang Anda cari. Jika Anda dapat meletakkan nilai-nilai Anda di peta alih-alih daftar, itu akan menyelesaikan masalah Anda. Cukup petakan nilai Anda ke nilai bukan null dan lakukan ini <c:if test="${mymap.myValue ne null}">style='display:none;'</c:if>atau Anda bahkan dapat memetakan ke style='display:none;dan hanya menampilkannya${mymap.myValue}

svachon.dll
sumber
Saya kira sintaksnya harus <c: if test = "$ {mymap [myValue] ne null}"> style = 'display: none;' </ c: if> Jika tidak, variabel "myValue" tidak dievaluasi.
Andreas
2
${fn:contains({1,2,4,8}, 2)}

ATAU

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

Jika Anda menggunakan EL 3.0+ , pendekatan terbaik dalam kasus ini adalah karena jawaban lain ini dijelaskan di topik lain:

Untuk Collectiongampangnya, gunakan saja Colleciton#contains() metode di 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>

Untuk Object[](array), Anda memerlukan minimal EL 3.0 dan memanfaatkan dukungan Lambda yang baru.

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

Jika Anda belum menggunakan EL 3.0, Anda perlu membuat fungsi EL kustom. [...]

Lucas Basquerotto
sumber
-1

Jika Anda menggunakan Spring Framework, Anda dapat menggunakan Spring TagLib dan 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
sumber
-1

Saya menemukan solusi ini luar biasa.

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

Output untuk kode di atas adalah

Daftar saya adalah [satu, dua, tiga]

Daftar saya berisi dua

Daftar saya berisi,

Saya harap ini membantu seseorang.

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

Ini bekerja dengan baik untuk saya.

Vladislav
sumber
18
Ini melakukan pemeriksaan setelah mengubah kedua elemen menjadi string. Daftar tersebut diubah menjadi string dan tidak diperiksa pada setiap elemen. Jika task.subscribers adalah list ["one", "two", "twentyone"], ini akan menjadi: true untuk customer = "one" (matching dua kali) false untuk customer = "three" (tidak ada yang cocok) true untuk customer = "dua puluh" (bukan yang Anda cari)
Ricardo Marimon
2
Menyadari peringatan rmarimon, jawaban ini cocok dengan kasus penggunaan saya.
CodeReaper