2013-05-02 31 views
38

Tôi đang cố gắng triển khai hệ thống plugin trong angularj cho phép người dùng định cấu hình "tiện ích con" nào họ sẽ thấy trên một trang nhất định. Mỗi widget được định nghĩa bởi một controller và một template (url). Có thể tạo ra một chỉ thị mà instantiates một bộ điều khiển, gọi nó với một mẫu và transcludes các kết quả nội dung?AngularJS Thủ công làm cho bộ điều khiển và mẫu

Mục đích là một cái gì đó như thế này:

<div class="widget" ng-repeat="widget in widgets"> 
    <widget controller="widget.controller" templateUrl="widget.templateUrl"></widget> 
</div> 
+1

Đây là bản chất những gì 'ngView' làm; mặc dù trường hợp sử dụng của bạn đơn giản hơn một chút, nhưng bạn có thể thấy [mã nguồn] của mình (https://github.com/angular/angular.js/blob/master/src/ng/directive/ngView.js) hữu ích. Về cơ bản, bạn lấy, thêm vào DOM, và sau đó '$ compile' mẫu của bạn và sau đó gán bộ điều khiển:' element.children(). Data ('$ ngControllerController', controller); '. Nếu tôi có thời gian sau ngày hôm nay tôi sẽ gửi một phản ứng hoàn chỉnh hơn. –

Trả lời

72

Có hai cách để làm điều này; một sử dụng các chỉ thị trợ giúp đã có sẵn (như ngIncludengController) và thứ hai là hướng dẫn sử dụng; phiên bản thủ công có thể nhanh hơn, nhưng tôi không thể chắc chắn.

The Way dễ dàng:

Phương pháp dễ dàng là để đơn giản tạo ra một nguyên tố mới với ngControllerngInclude thuộc tính, thêm nó vào yếu tố của chỉ thị, và sau đó $compile nó:

var html = '<div ng-controller="'+ctrl+'" ng-include="'+tpl+'"></div>'; 
element.append(html); 
$compile(element.contents())(scope); 

Hướng dẫn sử dụng:

Cách thủ công là tự làm những gì các chỉ thị này làm lần lượt; logic này là rất giống với những gì ngView hiện (mặc dù không có sự phức tạp). Chúng tôi lấy mẫu, lưu trữ nó trong $templateCache và sau đó nối nó vào DOM. Chúng ta tạo một phạm vi con mới và khởi tạo bộ điều khiển được cung cấp với nó và gán bộ điều khiển đó cho phần tử. Cuối cùng, chúng tôi $compile nó:

$http.get(tpl, { cache: $templateCache }) 
.then(function(response) { 
    templateScope = scope.$new(); 
    templateCtrl = $controller(ctrl, { $scope: templateScope }); 
    element.html(response.data); 
    element.children().data('$ngControllerController', templateCtrl); 
    $compile(element.contents())(templateScope); 
}); 

(Lưu ý rằng không có thu gom rác thải ở đây, mà bạn sẽ cần phải thực hiện nếu widget thay đổi)

Đây là một Plunker chứng minh cả hai phương pháp: http://plnkr.co/edit/C7x9C5JgUuT1yk0mBUmE?p=preview

+0

Điều này trông giống như một giải pháp tuyệt vời, rõ ràng và hợp lý, vấn đề với 'cách dễ dàng' là ng-include không được đánh giá, nó tải bộ điều khiển :) – perrohunter

+1

Dòng này rất tuyệt: '$ http.get (tpl, {cache: $ templateCache}) . sau đó (hàm (phản hồi) {...) '. Cảm ơn! – SimplGy

+0

Điều này không làm việc cho tôi trừ khi tôi gọi 'phạm vi. $ Apply()' – Simone

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