2015-10-02 35 views
15

Tôi đang sử dụng select2 version 4 với nhiều lựa chọn và tôi hỗ trợ người dùng thêm thẻ mới nhưng tôi muốn ngăn mọi người chọn thẻ mới nếu thẻ đó đã tồn tại trên chương trình phụ trợ của tôi.Khi sử dụng plugin jquery select2, làm cách nào để ngăn các thẻ mới được chọn nếu có giá trị hợp lệ từ cuộc gọi ajax đã được liệt kê?

Ngay bây giờ nếu người dùng nhập thẻ đã tồn tại và tôi có các thẻ : true thì thẻ sẽ hiển thị hai mục trong trình đơn thả xuống (thẻ hiện tại và thẻ mới). Dưới đây là một ví dụ:

enter image description here

như bạn có thể thấy, "testTag2" là một thẻ hợp lệ từ backend của tôi vì vậy nó xuất hiện trong việc lựa chọn nhưng vì templateResult chức năng và thực tế là thẻ : true nó cũng hiển thị dưới dạng mục thứ hai (khiến người dùng nghĩ rằng họ có thể chọn nó làm thẻ mới).

Có cách nào để chỉ hiển thị lựa chọn thẻ "MỚI" trong menu thả xuống không, nếu văn bản đó KHÔNG được liệt kê trong menu thả xuống dưới dạng tùy chọn khác?

đây là mã javascript của tôi:

function SetupAppTags() { 
$("#Tags").select2({ 
    theme: "classic", 
    width: "98%", 
    tags: true, 
    ajax: { 
     url: "/Tag/Search", 
     dataType: 'json', 
     delay: 300, 
     data: function(params) { 
      return { q: params.term }; 
     }, 
     processResults: function(data, params) { 
      return { results: data }; 
     }, 
     cache: false 
    }, 
    escapeMarkup: function(markup) { return markup; }, 
    minimumInputLength: 3, 
    templateResult: tagFormatResult, 
    templateSelection: tagSelectionResult 
}); 
} 

function tagFormatResult(tag) { 

if (tag.loading) { 
    return "Loading . . . <img src='/Content/Images/ajax-loader.gif' />"; 
} else { 

    if (tag.name) { 
     var existsAlready = $("#Tags option[value='" + tag.id + "']").length > 0; 
     if (existsAlready) { 
      return null; 
     } 
     return tag.name; 
    } 

    var length = $('#tagsContainer .select2-selection__choice').filter(function() { 
     return $(this).attr("title").toUpperCase() === person.text.toUpperCase(); 
    }).length; 

    if (length == 1) { 
     return null; 
    } 
    return tag.text + " [NEW]"; 
} 

}

+0

nó có thể là có thể cho bạn để tạo ra một fiddle cho việc này? Nếu Ajax là không thể thì ngay cả mảng dữ liệu đơn giản cũng đủ tốt. – vijayP

Trả lời

4

Xin vui lòng sửa tôi nếu tôi đã hiểu lầm câu hỏi của bạn. Nhưng theo sự hiểu biết của tôi, tôi đã đưa ra giải pháp sau đây.

Đối với mục đích giới thiệu tôi đã cài sẵn vài <option> yếu tố bên trong <select> hộp và thay vì thức ăn dữ liệu ajax-select2 Tôi đang sử dụng đồng bằng JavaScript array đối tượng bắt chước ajax phản ứng.

Các Cập nhật fiddle liên kết: https://jsfiddle.net/vijayP/akyzt9Ld/11/

HTML như sau:

<div id="tagsContainer"> 
    <select id="Tags" multiple="" name="Tags"> 
     <option value="white">white</option> 
     <option value="green">green</option> 
    </select> 
</div> 

Ở đây chúng ta có thể thấy rằng, các <option> hiện cuối cùng trong danh sách thả xuống có văn bản green.

JSON data đối tượng mà bắt chước ajax phản ứng trông giống như dưới đây:

var data = [{ id: 0, name:'yellow', text: 'yellow' }, 
       { id: 1, name:'green', text: 'green' }, 
       { id: 2, name:'cyan', text: 'cyan' }, 
       { id: 3, name:'violet', text: 'violet' }, 
       { id: 4, name:'gray', text: 'gray' } 
       ]; 

đây một lần nữa các green là ở vị trí thứ 2.

select2 khởi và hỗ trợ mã JavaScript đi như thế này:

var uniqueTexts = null; //array for holding unique text 
    $("#Tags").select2({ 
     tags: true, 
     data: data, 
     templateResult: tagFormatResult, 
     escapeMarkup: function (markup) { 
      uniqueTexts = null; 
      return markup; 
     }, 
     matcher: function (params, data) { 
      if(!uniqueTexts){ 
       uniqueTexts = []; 
      } 
      var modifiedData = null; 

      if ($.trim(params.term) === '' || data.text.indexOf(params.term) > -1) { 
       if(uniqueTexts.indexOf(data.text) == -1) 
       { 
        modifiedData = data; 
        uniqueTexts.push(modifiedData.text); 
       } 
      } 

      if(modifiedData) 
      { 
       return modifiedData; 
      } 

      return null; 
     } 
    }); 

    function tagFormatResult(tag) { 
     if (tag.loading) { 
      return "Loading . . . <img src='/Content/Images/ajax-loader.gif' />"; 
     } 
     else 
     { 
      var length = $('#tagsContainer .select2-selection__choice').filter(function() { 
       return $(this).attr("title").toUpperCase() === tag.text.toUpperCase(); 
      }).length; 

      if (length == 1) { 
       return tag.text; 
      } 

      if (tag.text) { 

       if(getOptionCount(tag.text) >1) 
        return tag.text; 
       else 
        return tag.text + " [NEW]"; 
      } 
      return tag.text + " [NEW]"; 
     } 
    } 

    function getOptionCount(tagText) 
    { 
     var count = 0; 
     var selectBoxOptions = $("#Tags option"); 
     $(selectBoxOptions).each(function(){ 
      if(tagText == $(this).text()) 
       count++;//increment the counter if option text is matching with tag text 
     }); 
     return count; 
    } 

var uniqueTexts là một mảng để giữ văn bản duy nhất được hiển thị cho người dùng cuối. Trong khi bắt đầu, chúng tôi đang đặt nó thành null. Vì vậy, ý tưởng là bất cứ khi nào người dùng tập trung vào hộp chọn HOẶC loại từ khóa tìm kiếm; matcher: gọi lại được gọi cho mỗi tùy chọn. Chúng tôi kiểm tra từng tùy chọn và xem tùy chọn đã có trong số uniqueTexts[] hay không. Nếu đó là lần xuất hiện đầu tiên thì chúng tôi cho phép nó hiển thị; nếu không chúng tôi trả lại null để tránh hiển thị lần thứ 2.

Tôi cũng đã thêm một bộ xử lý gọi lại escapeMarkup: được gọi bất cứ khi nào các tùy chọn được hiển thị cho người dùng cuối. Đây là điểm khi chúng tôi có thể đặt lại uniqueTexts thành null. Đây là vòng tròn hoàn chỉnh của chu kỳ. Một lần nữa người dùng có thể tập trung vào hoặc gõ vào để chọn hộp.

công trình như sau:

1) Trước tiên nó kiểm tra xem thẻ hiện tại đã được chọn hay không. Nếu nó đã được chọn thì đừng thêm "[NEW]" văn bản để tag.text

2) Thứ hai nó kiểm tra xem hiện tại tag.text hiện diện như select option văn bản nhiều hơn một lần hay không. Nếu nó có mặt ở nhiều nơi, thì cũng đừng thêm "[MỚI]" đến tag.text.

3) Trong tất cả các trường hợp khác, hãy tiếp tục và thêm "[NEW]" đến tag.text.

Tôi hy vọng điều này sẽ giúp bạn một chút. Cập nhật liên kết: https://jsfiddle.net/vijayP/akyzt9Ld/11/

+0

nếu tôi nhập thẻ 'xanh' và sau đó tôi nhập màu xanh lá cây một lần nữa, tôi thấy 2 lựa chọn trong menu thả xuống mà cả hai đều hiển thị "xanh lục". điều này dường như không trả lời câu hỏi. mục tiêu của tôi là chỉ hiển thị một mục và không có bản sao trong trình đơn thả xuống – leora

+0

@leora, tôi sẽ kiểm tra mục đó trong tuần tới. – vijayP

+0

@leora. Đã cập nhật câu trả lời. Xin hãy nhìn vào nó. – vijayP

9

Theo Select2 Options

Thay đổi cách lựa chọn được kết hợp khi tìm kiếm Khi người dùng lọc xuống kết quả bằng cách nhập thuật ngữ tìm kiếm vào hộp tìm kiếm, Select2 sử dụng một "đối sánh" nội bộ để đối sánh cụm từ tìm kiếm với kết quả. Khi sử dụng bộ dữ liệu từ xa , Select2 hy vọng rằng các kết quả trả về có đã được lọc.

Trình so khớp khóa Giá trị Một hàm lấy tham số tìm kiếm và đối tượng dữ liệu. Select2 sẽ chuyển các đối tượng dữ liệu riêng lẻ đã được chuyển trở lại từ bộ điều hợp dữ liệu vào trình ghép nối riêng lẻ để xác định nếu chúng được hiển thị. Chỉ các đối tượng cấp một sẽ là mới được chuyển vào, vì vậy nếu bạn đang làm việc với dữ liệu lồng nhau, bạn cần phải đối sánh riêng lẻ các đối tượng đó.

matcher: function (params, data) { 
    // If there are no search terms, return all of the data 
    if ($.trim(params.term) === '') { 
    return data; 
    } 

    // `params.term` should be the term that is used for searching 
    // `data.text` is the text that is displayed for the data object 
    if (data.text.indexOf(params.term) > -1) { 
    var modifiedData = $.extend({}, data, true); 
    modifiedData.text += ' (matched)'; 

    // You can return modified objects from here 
    // This includes matching the `children` how you want in nested data sets 
    return modifiedData; 
    } 

    // Return `null` if the term should not be displayed 
    return null; 
} 

Tôi nghĩ rằng đây là trường hợp điển hình của bạn, ngoại trừ việc bạn nên thay thế ("phù hợp") với (""), và thêm gì khác để nói thêm rằng "[NEW]" trong trường hợp của bạn.

Dữ liệu được trả về từ cuộc gọi ajax phải là đầu vào cho trình so khớp của bạn.

do đó, mã của bạn sẽ giống như thế:

matcher: function (params, data) { 
    // If there are no search terms, return all of the data 
    if ($.trim(params.term) === '') { 
    return data; 
    } 

    // `params.term` should be the term that is used for searching 
    // `data.text` is the text that is displayed for the data object 
    if (data.text.indexOf(params.term) > -1) { 
    var modifiedData = $.extend({}, data, true); 
    //match was found then just show it. 
    // modifiedData.text += ' (matched)'; 

    // You can return modified objects from here 
    // This includes matching the `children` how you want in nested data sets 
    return modifiedData; 
    } 
    else 
    { 
    //there is not match found , suggest adding NEW Tag. 
    modifiedData.text += '[NEW]'; 
    return modifiedData; 
    } 

    // Return `null` if the term should not be displayed 
    return null; 
} 
Các vấn đề liên quan