2010-02-15 95 views
38

Giả sử tôi có ba điều khiển danh sách thả xuống có tên là dd1, dd2dd3. Giá trị của từng danh sách thả xuống đến từ cơ sở dữ liệu. Giá trị của dd3 phụ thuộc vào giá trị của dd2dd2 giá trị của phụ thuộc vào giá trị của dd1. Bất cứ ai có thể cho tôi biết làm thế nào để tôi gọi servlet cho vấn đề này?Danh sách thả xuống xếp thứ tự trong JSP/Servlet

Trả lời

48

Về cơ bản có ba cách để đạt được điều này:

  1. Gửi mẫu cho một servlet trong sự kiện onchange của thả xuống 1 (bạn có thể sử dụng Javascript cho việc này), hãy để servlet được mục đã chọn của trình đơn thả xuống đầu tiên làm tham số yêu cầu, để cho nó có được các giá trị liên quan của danh sách thả xuống thứ 2 từ cơ sở dữ liệu dưới dạng Map<String, String>, để cho nó lưu trữ chúng trong phạm vi yêu cầu. Cuối cùng để JSP/JSTL hiển thị các giá trị trong danh sách thả xuống thứ 2. Bạn có thể sử dụng JSTL (chỉ cần thả jstl-1.2.jar trong /WEB-INF/lib) c:forEach thẻ cho việc này. Bạn có thể điền trước danh sách thứ nhất theo phương thức doGet() của Servlet được liên kết với trang JSP.Tuy nhiên

    <select name="dd1" onchange="submit()"> 
        <c:forEach items="${dd1options}" var="option"> 
         <option value="${option.key}" ${param.dd1 == option.key ? 'selected' : ''}>${option.value}</option> 
        </c:forEach> 
    </select> 
    <select name="dd2" onchange="submit()"> 
        <c:if test="${empty dd2options}"> 
         <option>Please select parent</option> 
        </c:if> 
        <c:forEach items="${dd2options}" var="option"> 
         <option value="${option.key}" ${param.dd2 == option.key ? 'selected' : ''}>${option.value}</option> 
        </c:forEach> 
    </select> 
    <select name="dd3"> 
        <c:if test="${empty dd3options}"> 
         <option>Please select parent</option> 
        </c:if> 
        <c:forEach items="${dd3options}" var="option"> 
         <option value="${option.key}" ${param.dd3 == option.key ? 'selected' : ''}>${option.value}</option> 
        </c:forEach> 
    </select> 
    

    Khi báo trước là điều này sẽ nộp toàn bộ hình thức và gây ra một "flash của nội dung", mà có thể có hại cho kinh nghiệm người dùng. Bạn cũng sẽ cần phải giữ lại các trường khác trong cùng một biểu mẫu dựa trên các tham số yêu cầu. Bạn cũng sẽ cần phải xác định trong servlet liệu yêu cầu có cập nhật một dropdown (giá trị dropdown con là null) hoặc để gửi biểu mẫu thực tế.

  2. In tất cả các giá trị có thể của 2 và thả xuống thứ 3 ra như một đối tượng javascript và làm cho việc sử dụng một hàm Javascript để điền vào danh sách thả xuống thứ 2 dựa trên mục đã chọn của dropdown 1 trong sự kiện onchange của thả xuống 1. Không gửi biểu mẫu và không cần chu kỳ máy chủ ở đây. Tuy nhiên

    <script> 
        var dd2options = ${dd2optionsAsJSObject}; 
        var dd3options = ${dd3optionsAsJSObject}; 
        function dd1change(dd1) { 
         // Fill dd2 options based on selected dd1 value. 
         var selected = dd1.options[dd1.selectedIndex].value; 
         ... 
        } 
        function dd2change(dd2) { 
         // Fill dd3 options based on selected dd2 value. 
         var selected = dd2.options[dd2.selectedIndex].value; 
         ... 
        } 
    </script> 
    
    <select name="dd1" onchange="dd1change(this)"> 
        <c:forEach items="${dd1options}" var="option"> 
         <option value="${option.key}" ${param.dd1 == option.key ? 'selected' : ''}>${option.value}</option> 
        </c:forEach> 
    </select> 
    <select name="dd2" onchange="dd2change(this)"> 
        <option>Please select parent</option> 
    </select> 
    <select name="dd3"> 
        <option>Please select parent</option> 
    </select> 
    

    Một caveat là điều này có thể trở nên không cần thiết kéo dài và tốn kém khi bạn có rất nhiều các mặt hàng. Hãy tưởng tượng rằng bạn có 3 bước của mỗi 100 mục có thể, điều đó có nghĩa là 100 * 100 * 100 = 1.000.000 mục trong các đối tượng JS. Trang HTML sẽ phát triển trên 1MB chiều dài.

  3. Sử dụng XMLHttpRequest trong Javascript để kích hoạt yêu cầu không đồng bộ cho servlet trong sự kiện onchange của menu thả xuống thứ 1, để servlet lấy mục được chọn của menu thả xuống thứ 1 làm tham số yêu cầu, để cho nó có được giá trị được liên kết trình đơn thả xuống thứ 2 từ cơ sở dữ liệu, trả lại nó dưới dạng chuỗi XML hoặc JSON. Cuối cùng, hãy để Javascript hiển thị các giá trị trong danh sách thả xuống thứ 2 thông qua cây DOM HTML (cách Ajax, như được đề xuất trước đó). Cách tốt nhất cho việc này là sử dụng jQuery.

    <%@ page pageEncoding="UTF-8" %> 
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 
    <!DOCTYPE html> 
    <html lang="en"> 
        <head> 
         <title>SO question 2263996</title> 
         <script src="http://code.jquery.com/jquery-latest.min.js"></script> 
         <script> 
          $(document).ready(function() { 
           $('#dd1').change(function() { fillOptions('dd2', this); }); 
           $('#dd2').change(function() { fillOptions('dd3', this); }); 
          }); 
          function fillOptions(ddId, callingElement) { 
           var dd = $('#' + ddId); 
           $.getJSON('json/options?dd=' + ddId + '&val=' + $(callingElement).val(), function(opts) { 
            $('>option', dd).remove(); // Clean old options first. 
            if (opts) { 
             $.each(opts, function(key, value) { 
              dd.append($('<option/>').val(key).text(value)); 
             }); 
            } else { 
             dd.append($('<option/>').text("Please select parent")); 
            } 
           }); 
          } 
         </script> 
        </head> 
        <body> 
         <form> 
          <select id="dd1" name="dd1"> 
           <c:forEach items="${dd1}" var="option"> 
            <option value="${option.key}" ${param.dd1 == option.key ? 'selected' : ''}>${option.value}</option> 
           </c:forEach> 
          </select> 
          <select id="dd2" name="dd2"> 
           <option>Please select parent</option> 
          </select> 
          <select id="dd3" name="dd3"> 
           <option>Please select parent</option> 
          </select> 
         </form> 
        </body> 
    </html> 
    

    ..where các Servlet đằng sau /json/options có thể trông như thế này:

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
        String dd = request.getParameter("dd"); // ID of child DD to fill options for. 
        String val = request.getParameter("val"); // Value of parent DD to find associated child DD options for. 
        Map<String, String> options = optionDAO.find(dd, val); 
        String json = new Gson().toJson(options); 
        response.setContentType("application/json"); 
        response.setCharacterEncoding("UTF-8"); 
        response.getWriter().write(json); 
    } 
    

    Ở đây, GsonGoogle Gson đó giúp giảm bớt chuyển đổi fullworthy đối tượng Java để JSON và ngược lại. Xem thêm How to use Servlets and Ajax?

+0

Mã tuyệt vời BalusC. Nếu bạn không phiền, tôi muốn hỏi một vài câu hỏi về phương pháp cuối cùng của bạn. Trong hàm fillOption() của bạn, dòng $ .getJSON, có vẻ như bạn gửi một yêu cầu GET tới servlet, nhưng bạn chỉ định url của servlet ở đâu. Ngoài ra, không có kết quả gửi lại từ servlet get store trong 'opts'. Vì vậy, là 'opts' như và đối tượng JSON? U có thể giải thích dòng này: $ ('> tùy chọn', dd) .remove(); nhiều thêm một chút? –

+0

@Harry Pham: '$ .getJSON' được ghi lại ở đây: http://api.jquery.com/jQuery.getJSON/ URL chỉ là'/json/options'. Ngoài ra, xem văn bản (không chỉ xem mã). Bạn chỉ có thể chọn bất kỳ URL nào bạn muốn. 'Opts' thực sự là chuỗi JSON được trả về bởi servlet. Đồng thời xem liên kết JSON để tìm hiểu thêm về nó.Nếu bạn biết Javabeans tốt, thì JSON trông khá quen thuộc. Các '$ ('> tùy chọn', dd) .remove()' loại bỏ tất cả các tùy chọn trước đó từ trình đơn thả xuống, nếu không nó sẽ chỉ được nối thêm, nối, vv .. Bằng cách này, nếu bạn thích câu trả lời, chỉ cần upvote nó. Tôi thấy rằng bạn gần như không bao giờ bỏ phiếu. – BalusC

+0

Tôi thấy ngay bây giờ, thông số đầu tiên của getJSON là url. Tôi là một thằng ngốc hoàn toàn. Về điều bình chọn, xin lỗi. Tôi thậm chí còn không nhận ra điều đó. Tôi sẽ nhìn lại bài viết cũ của tôi và cập nhật phiếu bầu. Cảm ơn nhiều. Nếu tôi có thêm câu hỏi, tôi sẽ quay lại và hỏi bạn. –

4

Bạn có thể cần nhiều servlet cho việc này.

Servlet 1: Tải các giá trị cho danh sách thả xuống đầu tiên từ cơ sở dữ liệu. Trên trang JSP, hãy xây dựng danh sách thả xuống. Trên người dùng chọn một giá trị gửi đến servlet hai.

Servlet 2: truy xuất giá trị từ danh sách đầu tiên và thực hiện tìm kiếm cơ sở dữ liệu cho các giá trị của danh sách thứ hai. Xây dựng danh sách thứ hai. Khi người dùng chọn giá trị thứ hai, hãy gửi nó tới servlet 3.

Servlet 3: truy lục giá trị được chọn trong menu thả xuống thứ hai và thực hiện tìm kiếm cơ sở dữ liệu để lấy giá trị cho menu thả xuống cuối cùng.

Bạn có thể muốn xem xét AJAX để làm cho việc phổ biến danh sách xuất hiện liền mạch với người dùng. jQuery có một số plugin rất hay để làm việc này khá dễ dàng nếu bạn sẵn sàng làm điều đó.


 <form action="servlet2.do"> 
      <select name="dd1" onchange="Your JavaScript Here"> 
       <option>.... 
      </select> 
    </form> 

Bạn có thể viết mã JavaScript mà nộp mẫu tại sự kiện onchange. Một lần nữa, nếu bạn sử dụng một thư viện hiện có như jQuery nó sẽ đơn giản hơn 10 lần.

+0

Tôi gặp cùng frend ý tưởng và cảm ơn sự hợp tác, nhưng tôi không biết làm thế nào tôi có thể gọi nó khi DD1 thua tập trung – deven

+0

Bạn có thể sử dụng một chút một javascript để nộp giá trị. Tôi sẽ thêm một số. –

4

Đánh giá theo câu hỏi của bạn, bạn thực sự không sử dụng khung web nhưng sử dụng servlet để hiển thị html.

Tôi sẽ rất tuyệt và nói rằng bạn đang ở khoảng một thập kỷ sau thời gian :), mọi người sử dụng JSP (và một khung công tác web như thanh chống) cho loại điều này. Tuy nhiên, có nói rằng, ở đây đi:

  1. Tạo trường ẩn trong biểu mẫu của bạn và đặt giá trị thành '1', '2' hoặc '3' tùy thuộc vào trình đơn thả xuống;
  2. Trong servlet của bạn, hãy nắm bắt giá trị này (request.getParamter()) và sử dụng câu lệnh 'case'/if/else để trả về các giá trị thả xuống thích hợp.

Tôi sẽ nói lại lần nữa, chỉ cần sử dụng khung công tác trên web hoặc jsp cũ đơn giản để thực hiện việc này.

3

Đó là một giải pháp đơn giản tuyệt vời. Tôi thích mã JQuery nhỏ như thế nào và thực sự đánh giá cao liên kết tới API GSON. Tất cả các ví dụ đã thực hiện điều này một cách dễ dàng.

Đã xảy ra sự cố khi xây dựng URL máy chủ JSON có tham chiếu đến SELECT mẹ (ví dụ: $(this).val()) [cần thiết để chỉ định thuộc tính :selected]. Tôi đã sửa đổi kịch bản một chút để bao gồm các bản cập nhật được đề xuất. Cảm ơn mã ban đầu.

<script> 
$(document).ready(function() 
{ 
    $('#dd1').change(function() { fillOptions('dd1', 'dd2'); }); 
    $('#dd2').change(function() { fillOptions('dd2', 'dd3'); }); 
}); 

function fillOptions(parentId, ddId) 
{ 
    var dd = $('#' + ddId); 
    var jsonURL = 'json/options?dd=' + ddId + '&val=' + $('#' + parentId + ' :selected').val(); 
    $.getJSON(jsonURL, function(opts) 
    { 
     $('>option', dd).remove(); // Clean old options first. 
     if (opts) 
     { 
      $.each(opts, function(key, value) 
      { 
       dd.append($('<option/>').val(key).text(value)); 
      }); 
     } 
     else 
     { 
      dd.append($('<option/>').text("Please select parent")); 
     } 
    }); 
} 
</script> 
Các vấn đề liên quan