2015-01-20 21 views
5

tôi thấy một ví dụ thực sự tốt của một loại AngularJS Bootstrap của Chọn chỉ thị:Làm cách nào tôi có thể sửa đổi trình đơn thả xuống AngularJS Bootstrap/chọn để không sử dụng jQuery?

http://jsfiddle.net/cojahmetov/3DS49/

này đáp ứng hầu hết các nhu cầu của tôi, nhưng nó sử dụng jQuery và chúng tôi không sử dụng thư viện đó.

Các jQuery sử dụng trong ví dụ này là rất tối thiểu nhưng tôi không biết làm thế nào tôi có thể thay thế các bộ định vị yếu tố đó trông như thế này:

bất cứ ai có thể cho tôi bất kỳ gợi ý như thế nào tôi có thể thay thế này:

switch (attrs.menuType) { 
    case "button": 
    $('button.button-label', element).html(item.name); 
    break; 
    default: 
    $('a.dropdown-toggle', element).html('<b class="caret"></b> ' + item.name); 
    break; 
} 

Vì vậy, nó sẽ hoạt động mà không cần jQuery? Lý tưởng nhất là tôi hy vọng rằng ai đó biết đủ để có thể đưa ra một phiên bản dựa trên phiên bản trong ui-bootstrap. Có lẽ điều này thậm chí có thể là thứ có thể được thêm vào ui-bootstrap để người khác sử dụng.

+0

Bạn đang nhắm mục tiêu/hỗ trợ những trình duyệt nào? – Problematic

+0

Có lẽ gán giá trị trực tiếp cho HTML không phải là một ý tưởng hay - bạn có thể sử dụng đối tượng phạm vi cho điều đó. Bạn có thể kiểm tra câu trả lời của tôi cho giải pháp thay thế hiện tại. –

+0

Kiểm tra câu trả lời. Bạn có cách tiếp cận sai ở đây: bạn không cần phải sử dụng .html() –

Trả lời

14

Idea trong Fiddle đó là tốt đẹp, nhưng tôi thấy việc thực hiện kinda lộn xộn. Vì vậy, những gì có thể làm gì? Vâng, hãy viết một chỉ thị thay thế dropdown trên đầu trang của ui-bootstrap, tất nhiên!

Hy vọng bạn thấy điều này hữu ích. Nó sẽ thực sự dễ sử dụng.

Cách sử dụng

<dropdown is-button 
      ng-model="vm.item" 
      items="vm.items" 
      callback="vm.callback(item)"> 
</dropdown> 

Vì vậy, bạn vượt qua trong các ng-model mà giữ lựa chọn ban đầu, nếu có. Giá trị mới được đặt từ chỉ thị. Trong số items bạn có bộ sưu tập gồm id-name cặp để chọn và chức năng callback nếu bạn cần. Nếu bạn chỉ định thuộc tính is-button, bạn sẽ nhận được điều khiển thả xuống kiểu nút.

Sau đó, trình điều khiển có thể trông giống như sau.

khiển

// Controller 
app.controller('Ctrl', function() { 
    var vm = this; 

    // items collection 
    vm.items = [{ 
     id: 0, 
     name: 'London' 
    },{ 
     id: 1, 
     name: 'Paris' 
    },{ 
     id: 2, 
     name: 'Milan' 
    }]; 

    // current item 
    vm.item = null; // vm.items[1]; 

    // directive callback function  
    vm.callback = function(item) { 
    vm.fromCallback = 'User selected ' + angular.toJson(item); 
    }; 
}); 

Logic cho chỉ thị dropdown là khá đơn giản, thực sự.

Chỉ JavaScript

// Dropdown directive 
app.directive('dropdown', function() { 
    return { 
    restrict: 'E', 
    require: '^ngModel', 
    scope: { 
     ngModel: '=', // selection 
     items: '=', // items to select from 
     callback: '&' // callback 
    }, 
    link: function(scope, element, attrs) { 
     element.on('click', function(event) { 
     event.preventDefault(); 
     }); 

     scope.default = 'Please select item'; 
     scope.isButton = 'isButton' in attrs; 

     // selection changed handler 
     scope.select = function(item) { 
     scope.ngModel = item; 
     if (scope.callback) { 
      scope.callback({ item: item }); 
     } 
     }; 
    }, 
    templateUrl: 'dropdown-template.html' 
    }; 
}); 

Chỉ HTML template

<div class="btn-group" dropdown> 

    <!-- button style dropdown --> 
    <button ng-if="isButton" 
      type="button" 
      class="btn btn-primary" 
      ng-bind="ngModel.name || default"> 
    </button> 
    <button ng-if="isButton" 
      type="button" 
      class="btn btn-primary dropdown-toggle" 
      dropdown-toggle> 
    <span class="caret"></span> 
    </button> 

    <!-- no button, plz --> 
    <a ng-if="!isButton" 
    class="dropdown-toggle" 
    dropdown-toggle href 
    ng-bind="ngModel.name || default"> 
    </a> 
    <span ng-if="!isButton" class="caret"></span> 

    <!-- dropdown items --> 
    <ul class="dropdown-menu" role="menu"> 
    <li ng-repeat="item in items"> 
     <a href="#" 
     ng-bind="item.name" 
     ng-click="select(item)"></a> 
    </li> 
    </ul> 

</div> 

Dưới đây là giao diện & cảm giác của việc thực hiện ban đầu. Ngoài mẫu bạn đã cung cấp, bạn sẽ lấy lại toàn bộ đối tượng chứ không phải chỉ là id.

enter image description here


liên quan Plunker đây http://plnkr.co/edit/bLWabx sử dụng angularjs 1.4.0-beta.3 và ui-bootstrap 0.12.0.

+1

Cảm ơn bạn đã dành thời gian để tìm ra giải pháp rất tốt đẹp này. Tôi sẽ thử điều này ngày hôm nay và xem tôi có bất kỳ câu hỏi nào không. – Alan2

+0

Đây là một giải pháp rất thanh lịch! Tuy nhiên, khi tôi chọn một mục, trang của tôi sẽ tải vào thư mục gốc. Làm thế nào chúng ta có thể ngừng hoạt động mặc định của 'ui.bootstrap.dropdown' để tải trang khi lựa chọn? – Thibs

+0

Tôi tìm thấy một cái gì đó hoạt động. Tôi đã thông qua $ event thành phương thức select của directive và sau đó gọi preventDefault() trên sự kiện này. Sẽ chờ đợi để xem giải pháp của bạn, không chắc chắn nếu tôi đang làm đúng cách. cảm ơn bạn! – Thibs

2

Chỉnh sửa: Tôi đã đúng, bạn không cần sử dụng .html() trong ví dụ này và thực tiễn không tốt nói chung. Lưu ý về cách sử dụng các đối tượng scope để thực hiện cùng một kết quả: http://jsfiddle.net/3DS49/162/

Đối với ví dụ tối thiểu bạn thấy ở đây, Bạn có thể sử dụng angular.element thay vì $ hoặc jQuery. angular.element là một tập con nhưng nó hỗ trợ .html().

Tuy nhiên, đó vẫn là một thực tế không tốt vì nội dung có thể được đặt trong scope và nội dung html có thể được đặt làm ràng buộc trực tiếp trong các mẫu nút.

Chỉnh sửa: angular.element không hỗ trợ bộ chọn. Bạn nên sử dụng một phương pháp tiếp cận bản địa cho điều đó (getElementById và bạn bè của nó). Tuy nhiên, hãy đảm bảo bạn không sử dụng các bộ chọn lọc cụ thể, như: trước tiên. Ví dụ .:

var elements = document.querySelectorAll(".myclass"); 

//it is up to you to iterate over the elements and call angular.element(element).html(yourValueHere) on each element. 

//NOTE: you can get document from $windowProvider.$get().document, or $window.document, depending on the place (you will use $window.document in this case). 

Sửa: kiểm tra trình duyệt hỗ trợ here - không có cách nào góc bản địa để hỗ trợ bộ chọn.

Để triển khai thực tế trong trường hợp cụ thể, bạn có thể thấy câu trả lời của @ChrisFrank an toàn. Tuy nhiên, hãy nhớ rằng bạn có thể bọc từng phần tử được lặp lại (ví dụ như trong câu trả lời của mình) với hàm angular.element để có được một jqLite (đối tượng được xây dựng trong tập con của jQuery - bạn không cần bất kỳ thư viện bổ sung nào).

3

Giải pháp này chỉ hỗ trợ IE9 + nếu bạn cần hỗ trợ các trình duyệt cũ, tôi có thể tìm giải pháp và cập nhật khác.

http://jsfiddle.net/3DS49/160/

scope.selectVal = function (item) { 
    function selector(sel, htmlCont) 
    { 
     var elems = document.querySelectorAll(sel); 
     Array.prototype.forEach.call(elems, function(el, i){ 
      el.innerHTML = htmlCont; 
     }); 
    } 
    switch (attrs.menuType) { 
     case "button": 
      selector('button.button-label', item.name); 
      break; 
     default: 
      selector('a.dropdown-toggle', '<b class="caret"></b> ' + item.name); 
      break; 
    } 
    scope.doSelect({ 
     selectedVal: item.id 
    }); 
}; 
+0

Nó không vorking tốt, khi bạn tạo thả xuống thứ hai: khi giá trị được chọn trong thứ hai, nó được thay đổi trong đầu tiên cũng ... http: // jsfiddle.net/6jj222w7/ cùng làm việc trong bản gốc - http://jsfiddle.net/v33sbzgy/ – Betlista

+0

Sẽ an toàn hơn khi chỉ định đúng các giá trị cho phạm vi, thay vì các cuộc gọi .html thô. Bạn cũng cần phải xác định đúng mẫu với các ràng buộc mong muốn –

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