15

Tôi đã tạo ra chỉ đơn giản tùy chỉnh AngularJs cho jquery này Plugin tuyệt vời jQuery-Select2 như sau:Angularjs Tuỳ chỉnh Select2 chỉ

Chỉ

app.directive("select2",function($timeout,$parse){ 
    return { 
     restrict: 'AC', 
     link: function(scope, element, attrs) { 
      $timeout(function() { 
       $(element).select2(); 
      },200); 
     } 
    }; 
}); 

Cách sử dụng trong HTML mẫu:

<select class="form-control" select2 name="country" 
data-ng-model="client.primary_address.country" 
ng-options="c.name as c.name for c in client.countries"> 
    <option value="">Select Country</option> 
</select> 

Nó hoạt động như mong đợi và bình thường 012 Thành phầnđược thay thế bằng select2 plugin.

Tuy nhiên, có một vấn đề, mặc dù đôi khi nó hiển thị giá trị mặc định tức là Select Country ở đây mặc dù giá trị mô hình thả xuống thích hợp được tự động chọn.

Bây giờ, nếu tôi tăng khoảng thời gian $timeout từ 200 lên một số giá trị cao có nghĩa là 1500, nó đang hoạt động nhưng trì hoãn việc hiển thị chỉ thị. Ngoài ra tôi nghĩ rằng đây không phải là giải pháp thích hợp cho nó, như dữ liệu của tôi là nhận được tải thông qua ajax.

Tôi cũng đã cố gắng để cập nhật chỉ thị như sau, nhưng không may mắn trong đó một trong hai:

app.directive("select2",function($timeout,$parse){ 
    return { 
     restrict: 'AC', 
     require: 'ngModel', 
     link: function(scope, element, attrs) { 
      var modelAccessor = $parse(attrs.ngModel); 
      $timeout(function() { 
       $(element).select2(); 
      }); 
      scope.$watch(modelAccessor, function (val) { 
       if(val) { 
        $(element).select2("val",val); 
       } 
      }); 
     } 
    }; 
}); 

PS: Tôi biết rằng có cũng tương tự như mô-đun hiện ui-select, nhưng nó đòi hỏi một số đánh dấu khác nhau dưới hình thức <ui-select></ui-select> và Ứng dụng của tôi đã được phát triển đầy đủ và tôi chỉ muốn thay thế hộp chọn bình thường bằng select2.

Vì vậy, bạn có thể vui lòng hướng dẫn tôi làm cách nào để tôi có thể giải quyết vấn đề này và đảm bảo rằng chỉ thị giữ đồng bộ hóa với hành vi mới nhất?

+0

Điều này có liên quan gì đến 'select2' không? Nếu bạn loại bỏ chỉ thị 'select2', và làm cho nó trở thành một phần tử chọn bình thường, nó có hoạt động như mong đợi không? –

+0

Có nó hoạt động như mong đợi nếu tôi loại bỏ như vậy. –

+2

Tôi cũng đang sử dụng 'select2' trong ứng dụng của mình nhưng tôi đang sử dụng [ui-select2] (https://github.com/angular-ui/ui-select2) là trình bao bọc của Angular cho nó, hiện không được dùng nữa . Select2 đã gây cho tôi rất nhiều đau buồn btw, tôi đề nghị bạn tránh nó nếu bạn có thể :) –

Trả lời

7

Nó có thể được đơn giản hơn bạn mong đợi!

hãy có một cái nhìn tại này Plunker

Về cơ bản, tất cả các plugin, Angularjs $ đồng hồ cần phải được dựa trên một cái gì đó. Tôi không chắc chắn 100% cho jQuery-select2; nhưng tôi nghĩ đó chỉ là sự kiện DOM bình thường của kiểm soát. (Và trong trường hợp của đồng hồ Angular $, đó là "vòng kiểm tra bẩn")

Ý tưởng của tôi là hãy tin tưởng jquery-Select2 và AngularJS để xử lý các sự kiện thay đổi đó.

Chúng ta chỉ cần xem cho sự thay đổi trong cách góc và cập nhật các chọn theo những cách Select2 của

var refreshSelect = function() { 
    if (!element.select2Initialized) return; 
    $timeout(function() { 
     element.trigger('change'); 
    }); 
}; 

//... 

scope.$watch(attrs.ngModel, refreshSelect); 

Chú ý: Tôi đã thêm vào 2 đồng hồ mới mà tôi nghĩ rằng bạn muốn có!

+0

Với kiểm soát như cách tiếp cận này sẽ không làm việc, bạn có thể làm cho nó hoạt động và đưa nó vào câu trả lời của bạn? xem [plunker] này (http://plnkr.co/edit/MrAwXPQuQU6FcmyOvekH) thay đổi trong lựa chọn được phản ánh trong biến phạm vi, nhưng thay đổi trong phạm vi biến không được phản ánh trong chọn – mohas

+0

Bạn có lỗi chính tả trong Plunkr của bạn. Bạn nên thay đổi ng-click của các nút để bao gồm cc. quá –

+1

Tôi thực sự khuyên bạn nên sử dụng sự kiện 'change.select2' thay vì 'thay đổi'. Tôi luôn nhận được các vòng lặp vô hạn của các sự kiện thay đổi cho đến khi tôi sử dụng [sự kiện không có giấy tờ 'change.select2'] (https://github.com/select2/select2/issues/3620) – smajl

3

Tôi không phải là quen thuộc với Select2 (vì vậy API thực tế để nhận và thiết lập các giá trị hiển thị trong việc kiểm soát có thể không đúng), nhưng tôi đề nghị này như một sự thay thế:

app.directive("select2",function($timeout){ 
    return { 
     restrict: 'AC', 
     require: 'ngModel', 
     link: function(scope, element, attrs, model) { 

      $timeout(function() { 
       element.select2(); 
      }); 

      model.$render = function() { 
       element.select2("val",model.$viewValue); 
      } 
      element.on('change', function() { 
       scope.$apply(function() { 
        model.$setViewValue(element.select2("val")); 
       }); 
      }) 
     } 
    }; 
}); 

Các $ đầu tiên timeout là cần thiết vì bạn đang sử dụng tùy chọn ng, do đó, các tùy chọn sẽ không nằm trong DOM cho đến chu kỳ phân hủy tiếp theo. Vấn đề với điều này là các tùy chọn mới sẽ không được thêm vào điều khiển nếu mô hình quốc gia sau đó được thay đổi bởi ứng dụng của bạn.

1

Nó không trực tiếp trả lời câu hỏi của bạn, nhưng hãy lấy nó như có một số người ra có những người muốn làm một cách tiếp cận hơn là gắn bó với jQuery select2.

Tôi đã xây dựng của riêng mình cho mục đích này bởi vì tôi đã không hài lòng những cái hiện có mà không chính xác theo nguyên tắc góc, HTML đầu tiên.

Vẫn còn ở giai đoạn đầu, nhưng tôi nghĩ rằng tất cả các tính năng đều hoạt động trong tất cả các trình duyệt hiện đại.

https://github.com/allenhwkim/angular-autocomplete

Đây là ví dụ

0

Tôi đã cố gắng tái tạo vấn đề của bạn và dường như nó hoạt động tốt. đây là fiddle tôi đến với:

http://jsfiddle.net/s24gLdgq/

Bạn có thể có một hành vi khác nhau tùy thuộc vào phiên bản của góc và/hoặc Select2 bạn đang sử dụng, bạn có thể xác định rằng?

Ngoài ra nếu bạn muốn ngăn chặn nhấp nháy, hãy nhớ ẩn thẻ <select> mặc định để không có gì được hiển thị trước khi phần tử select2 xuất hiện.

này cũng được thực hiện trong jsfiddle tôi với CSS

.form-control { width: 200px; opacity: 0 } 
3

Góc sẽ không thích dữ liệu mô hình được sửa đổi bởi plugin của bên thứ ba. Đoán của tôi dựa trên thực tế là bạn sử dụng $ timeout là có một điều kiện chủng tộc giữa Angular cập nhật các tùy chọn hoặc mô hình và plugin select2. Giải pháp mà tôi đưa ra là cập nhật phần lớn từ tay của Angular và làm theo cách thủ công từ chỉ thị, theo cách đó bạn có thể đảm bảo mọi thứ phù hợp bất kể ai đang sửa đổi. Đây là chỉ thị mà tôi đã đưa ra:

app.directive("select2",function($timeout,$parse){ 
    return { 
     restrict: 'AC', 
     link: function(scope, element, attrs) { 
      var options = [], 
       el = $(element), 
       angularTriggeredChange = false, 
       selectOptions = attrs["selectOptions"].split(" in "), 
       property = selectOptions[0], 
       optionsObject = selectOptions[1]; 
      // watch for changes to the defining data model 
      scope.$watch(optionsObject, function(n, o){ 
       var data = []; 
       // format the options for select2 data interface 
       for(var i in n) { 
        var obj = {id: i, text: n[i][property]}; 
        data.push(obj); 
       } 
       el.select2({data: data}); 
       // keep local copy of given options 
       options = n; 
      }, true); 
      // watch for changes to the selection data model 
      scope.$watch(attrs["selectSelection"], function(n, o) { 
       // select2 is indexed by the array position, 
       // so we iterate to find the right index 
       for(var i in options) { 
        if(options[i][property] === n) { 
         angularTriggeredChange = true; 
         el.val(i).trigger("change"); 
        } 
       } 
      }, true); 
      // Watch for changes to the select UI 
      el.select2().on("change", function(e){ 
       // if the user triggered the change, let angular know 
       if(!angularTriggeredChange) { 
        scope.$eval(attrs["selectSelection"]+"='"+options[e.target.value][property]+"'"); 
        scope.$digest(); 
       } 
       // if angular triggered the change, then nothing to update 
       angularTriggeredChange = false; 
      }); 

     } 
    }; 
}); 

Tôi đã thêm vào các thuộc tính select-optionsselect-model. Chúng sẽ được sử dụng để điền và cập nhật dữ liệu bằng cách sử dụng giao diện của select2. Đây là một html mẫu:

<select id="sel" class="form-control" select2 name="country" 
    select-selection="client.primary_address.country" 
    select-options="name in client.countries" > 
    <option value="">Select Country</option> 
</select> 
<div>Selected: {{client.primary_address.country}}</div> 

Xin lưu ý vẫn còn một số ngẫu nhiên mà có thể được thực hiện để chỉ thị và có bất kỳ điều tại giả định về đầu vào, chẳng hạn như "trong" trong thuộc tính select-tùy chọn. Nó cũng không thực thi các thuộc tính nhưng chỉ thất bại nếu chúng không tồn tại.

Cũng xin lưu ý rằng tôi đã sử dụng Select2 phiên bản 4, được chứng minh bằng el.val(i).trigger("change"). Bạn có thể phải hoàn nguyên một số điều nếu sử dụng phiên bản cũ hơn.

Dưới đây là jsfiddle demo chỉ thị đang hoạt động.