Chọn2 thả xuống nhưng cho phép giá trị mới của người dùng?


125

Tôi muốn có một danh sách thả xuống với một tập hợp các giá trị nhưng cũng cho phép người dùng "chọn" một giá trị mới không được liệt kê ở đó.

Tôi thấy rằng select2 hỗ trợ điều này nếu bạn đang sử dụng nó trong tagschế độ, nhưng có cách nào để làm điều đó mà không sử dụng thẻ không?


1
Select2 không bao giờ làm việc cho tôi, ít nhất là createdSearchChoice chưa bao giờ hoạt động với tôi trong 4.0.3 và tôi không muốn người dùng của mình đợi ajax hoàn thành để trả về cùng một từ khóa, vì vậy tôi phải triển khai thư viện của riêng mình, tôi chỉ chia sẻ nó bởi vì tôi nghĩ nó có thể giúp những người khác vẫn còn bối rối như tôi, xin vui lòng không bỏ phiếu nếu bạn không đồng ý với câu trả lời của tôi: github.com/razzbee/tagcomplete
razzbee

Câu trả lời:


100

Đối với phiên bản 4+, hãy kiểm tra câu trả lời dưới đây của Kevin Brown

Trong Chọn2 3.5.2 trở xuống, bạn có thể sử dụng một cái gì đó như:

$(selector).select2({
  minimumInputLength:1,
  "ajax": {
    data:function (term, page) {
      return { term:term, page:page };
    },
    dataType:"json",
    quietMillis:100,
    results: function (data, page) {
      return {results: data.results};
    },
    "url": url
  },
  id: function(object) {
    return object.text;
  },
  //Allow manually entered text in drop down.
  createSearchChoice:function(term, data) {
    if ( $(data).filter( function() {
      return this.text.localeCompare(term)===0;
    }).length===0) {
      return {id:term, text:term};
    }
  },
});

(được lấy từ một câu trả lời trong danh sách gửi thư select2, nhưng không thể tìm thấy liên kết ngay bây giờ)


4
Xin lỗi vì phản hồi muộn nhưng cảm ơn bạn rất nhiều vì giải pháp của bạn! Các poster khác, đã đăng một liên kết đến btw chính của bạn mà làm cho bạn gấp đôi tuyệt vời! :)
johnjohn

rrauenza tuyệt vời, chính xác những gì tôi đang tìm kiếm
Matthias S

4
Thêm ý selectOnBlur: truechí sẽ thực hiện công việc, vui lòng xem: stackoverflow.com/questions/25616520/
Kẻ

1
Chỉ cần một đầu cho các độc giả trong tương lai, bạn có thể muốn được sử dụng tags: []cùng với createSearchChoice.
Kevin Brown

5
Các fiddle liên kết ở trên dường như bị hỏng.
Wolfr

175

Các câu trả lời tuyệt vời cung cấp bởi @fmpwizard làm việc cho Select2 3.5.2 và dưới, nhưng nó sẽ không làm việc trong 4.0.0 .

Từ rất sớm (nhưng có lẽ không sớm như câu hỏi này), Select2 đã hỗ trợ "gắn thẻ": nơi người dùng có thể thêm giá trị của riêng họ nếu bạn cho phép họ. Điều này có thể được kích hoạt thông qua tagstùy chọn và bạn có thể chơi xung quanh với một ví dụ trong tài liệu .

$("select").select2({
  tags: true
});

Theo mặc định, điều này sẽ tạo ra một tùy chọn có cùng văn bản với cụm từ tìm kiếm mà họ đã nhập. Bạn có thể sửa đổi đối tượng được sử dụng nếu bạn đang tìm cách đánh dấu nó theo một cách đặc biệt hoặc tạo đối tượng từ xa sau khi nó được chọn.

$("select").select2({
  tags: true,
  createTag: function (params) {
    return {
      id: params.term,
      text: params.term,
      newOption: true
    }
  }
});

Ngoài việc phục vụ như một cờ dễ dàng phát hiện trên đối tượng được truyền qua select2:selectsự kiện, thuộc tính bổ sung còn cho phép bạn hiển thị tùy chọn hơi khác trong kết quả. Vì vậy, nếu bạn muốn báo hiệu trực quan thực tế rằng đó là một tùy chọn mới bằng cách đặt " (mới) " bên cạnh nó, bạn có thể làm một cái gì đó như thế này.

$("select").select2({
  tags: true,
  createTag: function (params) {
    return {
      id: params.term,
      text: params.term,
      newOption: true
    }
  },
  templateResult: function (data) {
    var $result = $("<span></span>");

    $result.text(data.text);

    if (data.newOption) {
      $result.append(" <em>(new)</em>");
    }

    return $result;
  }
});

Điều đó rất hữu ích @ Markus1980Wien
abiieez

Tôi nghĩ rằng tôi đã sử dụng đoạn trích này nhiều lần.
Sahu V Kumar

Nếu không hoạt động, hãy kiểm tra lại, bạn đã thêm tùy chọn này trên select2, không thêm vào tùy chọn ajax. cho select2 ajax
Zohaib

2
Cách làm việc của nó trong phiên bản select2 (4.0.6) bằng cách này: $ ("select"). Select2 ({tags: true, createTag: function (params) {return {id: params.term, text: params.term, newOption : true}}, templateResult: function (data) {var result = data.text; if (data.newOption) {result = result + '(new)';} return result;}}); cảm ơn @Kevin Brown
M. Salah

Đây phải là phản ứng hàng đầu. Tôi đã tìm kiếm một lúc cho điều này và tùy chọn này trả lời mọi câu hỏi tôi đã thấy về chủ đề này.
Justin

14

Chỉ vì mục đích giữ cho mã tồn tại, tôi đang đăng mã của @rrauenza Fiddle từ bình luận của anh ấy .

HTML

<input type='hidden' id='tags' style='width:300px'/>

jQuery

$("#tags").select2({
    createSearchChoice:function(term, data) { 
        if ($(data).filter(function() { 
            return this.text.localeCompare(term)===0; 
        }).length===0) 
        {return {id:term, text:term};} 
    },
    multiple: false,
    data: [{id: 0, text: 'story'},{id: 1, text: 'bug'},{id: 2, text: 'task'}]
});

2
Tôi đã đi đến câu đố, nhưng dường như nó không hoạt động với tôi trong Chrome. Bạn có thể xác nhận?
IcedDante

@IcedDante mã đang hoạt động. điểm trong fiddle chỉ là để cho thấy nó nên được thực hiện như thế nào (lựa chọn được ẩn trong fiddle)
Michel Ayres

4
Khi tôi đi đến fiddle tôi không thấy thả xuống select2 ở bất cứ đâu. Sẽ không tốt nếu có một ví dụ thực sự ... làm gì đó?
IcedDante

Làm thế nào tôi có thể thiết lập dữ liệu từ nguồn bên ngoài? Ý tôi là nếu tôi muốn tải các thành phố của một quốc gia được chọn và chính quốc gia được chọn đó là một điểm rơi?
Ali Baig

12

Vì nhiều câu trả lời trong số này không hoạt động trong 4.0+, nếu bạn đang sử dụng ajax, bạn có thể yêu cầu máy chủ thêm giá trị mới làm tùy chọn. Vì vậy, nó sẽ hoạt động như thế này:

  1. Người dùng tìm kiếm giá trị (yêu cầu ajax đến máy chủ)
  2. Nếu giá trị tìm thấy lớn, trả lại tùy chọn. Nếu không chỉ có máy chủ nối thêm tùy chọn đó như sau:[{"text":" my NEW option)","id":"0"}]
  3. Khi biểu mẫu được gửi, chỉ cần kiểm tra xem tùy chọn đó có trong db không và nếu không tạo nó trước khi lưu.


4

Cải thiện câu trả lời @fmpwizard:

//Allow manually entered text in drop down.
createSearchChoice:function(term, data) {
  if ( $(data).filter( function() {
    return term.localeCompare(this.text)===0; //even if the this.text is undefined it works
  }).length===0) {
    return {id:term, text:term};
  }
},

//solution to this error: Uncaught TypeError: Cannot read property 'localeCompare' of undefined

Tôi đã sử dụng điều này với một sửa đổi nhỏ, tôi sẽ đưa ra câu trả lời của mình trong một giây nhưng cảm ơn.
Sam


1
var text = 'New York Mills';
var term = 'new york mills';
return text.localeCompare(term)===0;

Trong hầu hết các trường hợp, chúng ta cần so sánh các giá trị với thanh ghi không nhạy. Và mã này sẽ trả về false, điều này sẽ dẫn đến việc tạo các bản ghi trùng lặp trong cơ sở dữ liệu. Ngoài ra, String.prototype.localeCompare () không được trình duyệt Safary hỗ trợ và mã này sẽ không hoạt động trong trình duyệt này;

return this.text.localeCompare(term)===0;

sẽ thay thế tốt hơn để

return this.text.toLowerCase() === term.toLowerCase();

1

Cảm ơn các bạn đã giúp đỡ, tôi đã sử dụng mã bên dưới trong Codeigniter II đang sử dụng phiên bản: 3.5.2 của select2.

var results = [];
var location_url = <?php echo json_encode(site_url('job/location')); ?>;
$('.location_select').select2({
    ajax: {
        url: location_url,
        dataType: 'json',
        quietMillis: 100,
        data: function (term) {
            return {
                term: term
            };
        },
        results: function (data) {
            results = [];
            $.each(data, function(index, item){
                results.push({
                    id: item.location_id,
                    text: item.location_name
                });
            });
            return {
                results: results
            };
        }
    },
    //Allow manually entered text in drop down.
    createSearchChoice:function(term, results) {
        if ($(results).filter( function() {
            return term.localeCompare(this.text)===0; 
        }).length===0) {
            return {id:term, text:term + ' [New]'};
        }
    },
});
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.