2013-07-22 26 views
29

Cho một chỉ thị (container1) với transclude và một phạm vi cô lập, khi chỉ thị được liên kết sau đó tôi có những phạm vi:Tại sao phạm vi của ng-transclude không phải là một đứa trẻ trong phạm vi chỉ thị của nó - nếu chỉ thị có phạm vi bị cô lập?

Scope 004   <-- scope of the body 
    Scope 005  <-- scope of directive container1 
    Scope 006  <-- scope of the ng-transclude 

tôi mong đợi:

Scope 004   <-- scope of the body 
    Scope 005  <-- scope of the directive 
     Scope 006 <-- scope of the ng-transclude 

Nếu chỉ thị tương tự có phạm vi được chia sẻ thay vì phạm vi bị cô lập, tôi nhận được kết quả mong đợi.

Điều này gây cho tôi một vấn đề bởi vì, nếu nội dung nhúng chứa một chỉ thị (component1) với một phạm vi cô lập, tôi nhận được:

Scope 004    <-- scope of the body 
    Scope 005   <-- scope of the directive 
    Scope 006   <-- scope of the ng-transclude 
      Scope 007 <-- scope of directive component1 

Tôi muốn sử dụng các chỉ thị như thế này:

<container1> 
    <component1 data="objectExposedInContainer1"/> 
</container1> 

Nhưng điều đó không hiệu quả, bên trong component1, $scope.dataundefinedobjectExposedInContainer1 không nằm đúng phạm vi.

Tôi có hai câu hỏi:

  • Tại sao ng-transclude 's phạm vi không phải là một đứa trẻ phạm vi chỉ thị của nó nếu chỉ thị có phạm vi bị cô lập? Đây có phải là một lỗi?
  • Nếu đó không phải là lỗi, làm cách nào để chỉ thị vùng chứa chuyển dữ liệu đến nội dung của nó, nếu không phải bằng cách đặt các thuộc tính như tôi đã thử.

Đây là ví dụ mẫu không hoạt động: http://plnkr.co/edit/NDmJiRzTF9e5gw8Buht2?p=preview. Bởi vì Plunker được xây dựng với Anguar, thật khó để gỡ lỗi với Batarang. Tôi khuyên bạn nên tải xuống mã cục bộ. Nhận xét ra line 10 của app.js để làm cho nó hoạt động bằng cách sử dụng một phạm vi chia sẻ.

+0

1) Không, bạn đã chính xác những gì bạn yêu cầu - phạm vi của chỉ thị bị cô lập. 2) Sử dụng bộ điều khiển dùng chung. –

+0

@Joe Gauterin, hãy xem mẫu mới này: http://plnkr.co/edit/Bv7B4OokkLi8bIctCIl3. Ở đây, 'container1' chứa' thành phần1' nhưng không sử dụng 'ng-transclude'. Lần này, ngay cả khi cả hai đều có phạm vi phân lập, phạm vi của chúng có mối quan hệ cha/mẹ chính xác. Sự hiện diện của 'ng-transclude' làm thay đổi kết quả. – Sylvain

Trả lời

29

Tại sao phạm vi của ng-transclude không phải là con của phạm vi chỉ thị của nó nếu chỉ thị có phạm vi riêng biệt?

ng-transclude được thiết kế để cho phép chỉ thị để làm việc với nội dung tùy ý, và phạm vi riêng biệt được thiết kế để cho phép chỉ thị để đóng gói dữ liệu của họ.

Nếu ng-transclude không lưu giữ phạm vi như vậy, bất kỳ nội dung tùy ý nào mà bạn đang chuyển sẽ cần biết chi tiết triển khai của chỉ thị của bạn (nghĩa là cần biết những gì có sẵn trên phạm vi cô lập mà bạn đã tạo).

Nếu đó không phải là lỗi, cách chỉ thị vùng chứa chuyển dữ liệu đến nội dung của nó, nếu không bằng cách đặt thuộc tính như tôi đã thử.

Nếu chỉ thị vùng chứa và chỉ thị được kết hợp - tức là bạn đã viết cả hai và cần chúng cùng nhau hành động - thì chúng sẽ liên lạc qua bộ điều khiển dùng chung.

Nếu chỉ thị vùng chứa được cho là đưa nội dung vào phạm vi của trẻ em (ví dụ:ng-lặp lại), sau đó bạn không nên sử dụng một phạm vi bị cô lập.


Các tài liệu góc khá rõ ràng về những gì hành vi được coi là:

"Trong một thiết lập điển hình widget tạo ra một phạm vi cô lập, nhưng nhúng không phải là một đứa trẻ, nhưng một anh chị em của phạm vi cô lập này làm cho tiện ích có thể có trạng thái riêng tư và việc chuyển đổi bị ràng buộc với phạm vi phụ huynh (được cách ly). "

+1

Cảm ơn câu trả lời toàn diện này. – Sylvain

+0

Tôi đã tạo một tác phẩm nhưng tôi không chắc chắn về cách thực hành tốt nhất, tôi hy vọng các bạn có thể dành thời gian rảnh để kiểm tra? Đó là một hack transclude tùy chỉnh đảm bảo việc tạo ra một phạm vi cô lập con mới trong giai đoạn liên kết. Điều này tạo ra cha -> hệ thống phân cấp con để chúng ta có thể sử dụng $ emit và $ on trong bộ điều khiển. https://gist.github.com/meanJim/1c3339bde5cbeac6417d – Jim

+1

Tôi cũng đã áp dụng cách tiếp cận tương tự như @Jim và tôi cũng không chắc liệu đó có phải là phương pháp hay nhất hay không. Bạn có thể tìm thấy một plunk ở đây: http://plnkr.co/edit/Ph5lMl0ol8ayXOFr7eal –

11

bạn có thể tự transclude phần tử con

link: function(scope, element, attrs, ctrl, transclude) { 
    transclude(scope, function(clone, scope) { 
     element.find('.transclude-placeholder').append(clone); 
    }); 
} 
3

Câu trả lời đầu là chỉ đúng cho góc lên đến v1.2.

Kể từ khi Angular v1.3 hành vi đã thay đổi và hiện hành xử lý chính xác như được mô tả trong phần "Tôi mong đợi" của câu hỏi, làm cho câu hỏi này lỗi thời đối với Angular v1.3 +.

Nguồn: https://github.com/angular/angular.js/commit/fb0c77f0b66ed757a56af13f81b943419fdcbd7f

+0

Xin chào, tôi vừa cập nhật mẫu lên 1.3.15 và nó vẫn làm điều tương tự. http://plnkr.co/edit/PGsJRngCTCzstz85V80C?p=preview. Tôi đã thử nó với 1,4 quá và tôi đã nhận được kết quả tương tự. Bình luận? – Sylvain

+0

Trong thực tế, hôm nay tôi đã hỏi một câu hỏi mà tôi đã tự cung cấp câu trả lời dựa trên câu trả lời này! http://stackoverflow.com/questions/38267288/force-scope-to-named-slot-with-ng-transclude/38273990#38273990 –

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