2015-05-16 20 views
5

Vấn đề:Knockout 'với' ràng buộc và Select2 trong jQuery thoại

Các Select2 jQuery plugin không hoạt động khi sử dụng trên một hộp thoại jQuery lồng nhau dưới một yếu tố mà sử dụng loại trực tiếp with databinding. Hủy bỏ ràng buộc with và select2 hoạt động tốt. Nếu with bị ràng buộc với thuộc tính lồng nhau thì nó ngừng hoạt động.

Bối cảnh:

Vì vậy, tôi phải chiến đấu cho phần tốt nhất là 3 giờ cố gắng để có được Select2 để làm việc trên một hình thức thoại jQuery .... nói về pi $$ ing lên cây sai ngôn , Tôi nghĩ nó hoàn toàn là hộp thoại jQuery và select2. Nó có thể làm việc ngay từ đầu với sửa lỗi _allowInteraction. Cho đến khi tôi phá vỡ vấn đề ngay xuống các bước đơn giản và nguyên nhân bắt đầu tiết lộ chính nó. Vấn đề là với ràng buộc with.

Disclaimer

Xin lỗi vì tôi làm việc cho một công ty giống lừa rằng khối jsFiddle. Ngoài ra tôi đã chia nhỏ việc triển khai của mình cho mục đích minh họa vì mô hình thực tế là khá lớn.

// models 
 

 
function Department() { 
 
    this.name   = ko.observable('dept1'); 
 
    this.selectedTeam = ko.observable(new Team()); 
 
} 
 
    
 
function Team() { 
 
    this.name = ko.observable('team1'); 
 
} 
 
    
 
function MainModel() { 
 
    this.department = new Department(); 
 
    this.showTeam = function() { 
 
    $('#addTeamDialog').dialog('open'); 
 
    }; 
 
} 
 

 
// setup 
 

 
ko.applyBindings(new MainModel()); 
 
    \t 
 
$('#addTeamDialog').dialog({ 
 
    // fix allow select2 to work on the jq dialog 
 
    _allowInteraction: function (event) { 
 
    return !!$(event.target).is(".select2-input") || this._super(event); 
 
    } \t \t 
 
}); 
 
    \t 
 
$('#someList').select2({ 
 
    data: [ 
 
    { id: 0, text: 'enhancement' }, 
 
    { id: 1, text: 'bug' }, 
 
    { id: 2, text: 'duplicate' }, 
 
    { id: 3, text: 'invalid' }, 
 
    { id: 4, text: 'wontfix' } 
 
    ] 
 
});
<link href="http://code.jquery.com/ui/1.11.4/themes/ui-lightness/jquery-ui.css" rel="stylesheet"/> 
 
<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet" /> 
 

 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="http://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.full.min.js"></script> 
 

 
<button data-bind="click: showTeam">Add Team</button> 
 

 
<div id="addTeamDialog"> 
 
    <fieldset data-bind="with: department"> 
 
    
 
    <div class="lite-dialog-field"> 
 
     <div class="label"> 
 
     <span data-bind="text: name"></span> 
 
     </div> 
 
     <div class="field"> 
 
     <input type="hidden" id="someList" /> 
 
     </div>  
 
    </div> 
 
     
 
    </fieldset> 
 
</div>

Loại bỏ các data-bind trên fieldset và Select2 hoạt động tốt.

Khi data-bind trên fieldset được đặt thành department select2 hoạt động tốt.

Khi data-bind trên fieldset được đặt thành department.selectedTeam select2 không hoạt động.

+0

Mã bạn đã đăng không hoàn toàn dường như là đủ để tái tạo kịch bản của bạn (ví dụ không có 'select's hoặc mã có liên quan của bất cứ loại nào?). – Jeroen

+0

Điều gì mang lại? Đầu vào bị ẩn trên đánh dấu với id someList là vùng chứa cho điều khiển select2. Trong phần thiết lập, bạn có thể thấy tôi gọi $ ('# someList'). Select2 ({..}). Điều này chuyển đổi phần tử này thành danh sách select2. Tui bỏ lỡ điều gì vậy? Downvote khắc nghiệt .... –

+1

Tôi đã sửa chữa. Xin lỗi. - Tôi đã chỉnh sửa câu hỏi của bạn một chút, nếu không hệ thống sẽ không cho phép tôi hoàn tác phiếu bầu của mình. Tôi cũng đã rút lại cuộc bầu cử gần như bây giờ tôi thấy không đủ nỗ lực để sử dụng mã được đăng để repro vấn đề (mặc dù tôi vẫn không chắc chắn 100% cách làm như vậy, nhưng những người khác có thể thấy mọi thứ rõ ràng hơn có thể giúp đỡ). – Jeroen

Trả lời

4

Khi bạn làm việc với Knockout, bạn nên bọc các thư viện bên ngoài như select2 trong các kết buộc. Trong khi bạn chỉ khởi tạo chúng một lần, các ràng buộc như with, template hoặc foreach có thể sửa đổi DOM bất kỳ lúc nào sau đó.

Bạn phải đối mặt với sự nguy hiểm của một trong hai

  1. khởi Select2 quá sớm khi Knockout đã không trả lại bất cứ điều gì chưa, hoặc
  2. Knockout ném đi và tái dựng hình đánh dấu tại một điểm sau đó, do đó bạn select2 đột nhiên không bị ràng buộc nữa

Ví dụ: điều này sẽ xảy ra khi Department.selectedTeam bị thay đổi.

Tôi đã tìm thấy liên kết select2 nhanh chóng và bẩn từ Knockouts 'rniemeyer himself here. Ngoài ra, tôi chỉ thay đổi đánh dấu select2 thành một tiêu chuẩn <select> và thực hiện MainModel.department thành một quan sát thích hợp để đảm bảo tính nhất quán và an toàn.

ko.bindingHandlers.select2 = { 
 
    init: function(element, valueAccessor) { 
 
     var options = ko.toJS(valueAccessor()) || {}; 
 
     setTimeout(function() { 
 
      $(element).select2(options); 
 
     }, 0); 
 
    } 
 
}; 
 

 
// models 
 

 
function Department() { 
 
    this.name   = ko.observable('dept1'); 
 
    this.selectedTeam = ko.observable(new Team()); 
 
}; 
 
    
 
function Team() { 
 
    this.name  = ko.observable('team1'); 
 
    this.values = ["red", "grey", "blue"]; 
 
    this.selected = ko.observableArray(["blue"]); 
 
}; 
 
    
 
function MainModel() { 
 
    this.department = ko.observable(new Department()); 
 
    this.showTeam = function() { 
 
    $('#addTeamDialog').dialog('open'); 
 
    }; 
 
}; 
 

 
// setup 
 

 
ko.applyBindings(new MainModel()); 
 
    \t 
 
$('#addTeamDialog').dialog({ 
 
    // fix allow select2 to work on the jq dialog 
 
    _allowInteraction: function (event) { 
 
    return !!$(event.target).is(".select2-input") || this._super(event); 
 
    } \t \t 
 
});
select { 
 
    width: 200px; 
 
}
<link href="http://code.jquery.com/ui/1.11.4/themes/ui-lightness/jquery-ui.css" rel="stylesheet"/> 
 
<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet" /> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="http://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.full.min.js"></script> 
 

 
<button data-bind="click: showTeam">Add Team</button> 
 

 
<div id="addTeamDialog"> 
 
    <fieldset data-bind="with: department().selectedTeam"> 
 
    
 
    <select data-bind="options: values, 
 
         selectedOptions: selected, 
 
         select2: { placeholder: 'pick some colors' }"> 
 
    </select> 
 
     
 
    </fieldset> 
 
</div>

+0

Cảm ơn janfoeh. Thật không may nó đã không giải quyết vấn đề của tôi. Độ sâu của thuộc tính được sử dụng với ngữ cảnh ràng buộc 'có' dường như ảnh hưởng đến việc kiểm soát select2 có hoạt động hay không. Tôi đưa vào bình luận của bạn về gói tất cả các thư viện bên ngoài trong một ràng buộc và sẽ chuyển đổi của tôi để điều đó ngay sau khi tôi có thể hiểu và sửa vấn đề này –

+0

@AlanAlcock Tôi là một chút bối rối từ bình luận của bạn cho dù bạn đã thử sử dụng select2 thông qua một ràng buộc hay không? Bởi vì đó là cốt lõi của câu trả lời của tôi. – janfoeh

+0

janfoeh - trong sự vội vàng của tôi, tôi đã không nghiên cứu phản ứng của bạn một cách chính xác nhưng điều này đã thực sự giải quyết vấn đề và quan trọng hơn là dạy tôi đánh giá cao và bọc các thư viện bên ngoài trong trình xử lý ràng buộc. Rất cảm ơn vì sự giúp đỡ của bạn. –

Các vấn đề liên quan