Đánh giá chuỗi list.contains trong JSTL


89

Tôi cần ẩn một phần tử nếu các giá trị nhất định có trong JSP

Các giá trị được lưu trữ trong một Danh sách nên tôi đã thử:

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

Nhưng, nó không hoạt động.

Làm cách nào tôi có thể đánh giá nếu một danh sách chứa một giá trị trong JSTL, danh sách và các giá trị là chuỗi.


17
Lưu ý rằng cú pháp đã cho hoạt động như mục đích kể từ EL 2.2 (được đưa vào như một phần của Servlet 3.0 / JSP 2.2 được phát hành vào tháng 12 năm 2009).
BalusC

Câu trả lời:


70

Đáng buồn thay, tôi nghĩ rằng JSTL không hỗ trợ bất cứ điều gì ngoài việc lặp lại tất cả các phần tử để tìm ra điều này. Trước đây, tôi đã sử dụng phương thức forEach trong thư viện thẻ lõi:

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

Sau khi điều này chạy, $ {chứa} sẽ bằng "true" nếu myList chứa myValue.


10
hoạt động tốt nếu danh sách nhỏ. Chỉ cần nhận ra rằng có một chi phí hiệu suất để làm theo cách này.
Chii 29/09/09

Vâng, sẽ có nếu bạn đạt đủ cao. Tôi đã sử dụng nó cho các bộ sưu tập gồm 10-20 thứ và chưa gặp bất kỳ vấn đề nào về hiệu suất. Điều tôi nghĩ là tồi tệ hơn là số dòng của JSTL. Tuy nhiên, tôi nghĩ đây là cách duy nhất mà không cần thiết lập TLD của riêng bạn (điều này không quá khó và có thể rất đáng giá).
Kaleb Brasee 29/09/09

97

không có tính năng tích hợp nào để kiểm tra điều đó - những gì bạn sẽ làm là viết hàm tld của riêng bạn để nhận một danh sách và một mục, đồng thời gọi phương thức chứa () của danh sách. ví dụ

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

Sau đó, tạo một lớp có tên Yourclass và thêm một phương thức tĩnh có tên là contains với chữ ký ở trên. Tôi chắc chắn rằng việc triển khai phương pháp đó khá tự giải thích:

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

Sau đó, bạn có thể sử dụng nó trong jsp của mình:

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

Thẻ có thể được sử dụng từ bất kỳ JSP nào trong trang web.

chỉnh sửa: thêm thông tin về tệp tld - thêm thông tin ở đây


4
Tôi khuyên bạn nên sử dụng Collectionthay vì Listtrong taglib - nó hoạt động giống nhau nhưng hỗ trợ loại bộ sưu tập giống như Sets
Ralph

28

Một cách khác để thực hiện việc này là sử dụng Map (HashMap)các cặp Khóa, Giá trị đại diện cho đối tượng của bạn.

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

Trong JSTL

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

Điều này sẽ trả về true nếu cặp này tồn tại trong bản đồ


2
Đây cũng là cách ưa thích của tôi, thiết lập các bản đồ băm trong mô hình chế độ xem cho mọi thứ tôi cần trong một chế độ xem. Chúng tích hợp độc đáo với cú pháp EL và nhanh như chớp khi tìm kiếm.
Boris B.

Chỉ một điều nữa, nếu khóa tồn tại nhưng giá trị là null hoặc rỗng thì nó sẽ trả về false.
Zai

1
Hoặc nếu Bản đồ chứa boolean test="${isPresentByValue[myValue]}",.
Noumenon

15

Bạn cần sử dụng hàm fn:contains()hoặc 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>

hoặc là

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

Lưu ý: Điều này sẽ hoạt động như thế nàomylist.toString().contains("apple")và nếu đây không phải là điều bạn đang tìm kiếm, hãy sử dụng một cách tiếp cận khác tốt hơn.


2
Đây không phải là cách tiếp cận chính xác. Về cơ bản, nó sẽ hoạt động như mylist.toString().contains("apple")vậy hoàn toàn không phải như những gì bạn mong đợi ban đầu.
BalusC

ồ .. vâng, đây không phải là điều tôi mong đợi. Dù sao tôi sẽ cập nhật câu trả lời của tôi với tiền phạt này.
tk_

2

Sau đây là một cách giải quyết hơn là một câu trả lời cho câu hỏi của bạn nhưng nó có thể là những gì bạn đang tìm kiếm. Nếu bạn có thể đặt các giá trị của mình vào bản đồ thay vì danh sách, điều đó sẽ giải quyết được vấn đề của bạn. Chỉ cần ánh xạ các giá trị của bạn thành một giá trị không rỗng và làm điều này <c:if test="${mymap.myValue ne null}">style='display:none;'</c:if>hoặc bạn thậm chí có thể ánh xạ đến style='display:none;và chỉ cần xuất${mymap.myValue}


Tôi đoán cú pháp phải là <c: if test = "$ {mymap [myValue] ne null}"> style = 'display: none;' </ c: if> Nếu không, biến "myValue" không được đánh giá.
Andreas

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

HOẶC LÀ

  <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

Nếu bạn đang sử dụng EL 3.0+ , cách tiếp cận tốt nhất trong trường hợp này là như câu trả lời khác này được giải thích trong một chủ đề khác:

Đối với một Collectionthật dễ dàng, chỉ cần sử dụng các Colleciton#contains() phương pháp trong 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>

Đối với Object[](mảng), bạn cần tối thiểu EL 3.0 và sử dụng hỗ trợ Lambda mới của nó.

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

Nếu bạn chưa sử dụng EL 3.0, bạn cần tạo một hàm EL tùy chỉnh. [...]


-1

Nếu bạn đang sử dụng Spring Framework, bạn có thể sử dụng Spring TagLib và 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

Tôi thấy giải pháp này thật tuyệt vời.

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

Đầu ra cho đoạn mã trên là

Danh sách của tôi là [một, hai, ba]

Danh sách của tôi có hai

Danh sách của tôi chứa,

Tôi hi vọng nó giúp ích cho ai đó.


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

Cái này làm việc tốt cho tôi.


18
Đây là việc kiểm tra sau khi chuyển đổi cả hai phần tử thành chuỗi. Danh sách được chuyển đổi thành một chuỗi và không được kiểm tra trên cơ sở mỗi phần tử. Nếu task.subscriber là danh sách ["một", "hai", "hai mươi một"] thì nó sẽ là: true cho customer = "một" (so khớp hai lần) false cho customer = "ba" (không khớp) true cho customer = "hai mươi" (mà không phải là điều bạn đang tìm kiếm)
Ricardo Marimon

2
Nhận thức được cảnh báo của rmarimon, câu trả lời này phù hợp với trường hợp sử dụng chính xác của tôi.
CodeReaper
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.