2013-04-04 30 views
10

thiết lập chỉ thị của tôi là như sau:

<div data-directive-a data-value="#33ff33" data-checked="true"> 
    <div data-directive-b></div> 
</div> 
  • Tôi đang sử dụng nhúng để đảm bảo directiveB được kết xuất.
  • directiveA có hộp kiểm có nghĩa là thay đổi một số giá trị bất kỳ khi nào được chọn.
  • giá trị này cần phải truy cập được trong phạm vi của directiveAdirectiveB.

Tôi đã cố gắng thực hiện điều này, nhưng chỉ bằng cách tham chiếu $$prevSibling - có cách nào tốt hơn không?

Dưới đây là các mã: http://jsfiddle.net/janeklb/yugQf/ (trong mẫu này, nhấp vào hộp kiểm đơn giản có nghĩa là để "dọn sạch" giá trị)

- hơn

Một chút chiều sâu: Các 'nội dung' của directiveA (mà đang được chuyển đổi vào nó) không phải lúc nào cũng là directiveB. Các chỉ thị khác như directiveB cũng sẽ kết thúc ở đó. Các loại "directiveB" sẽ luôn được sử dụng trong phạm vi directiveA.

+2

tôi khuyên bạn nên sử dụng đòi hỏi phải định nghĩa trong chỉ thị và thông qua bộ điều khiển cha mẹ để điều khiển con –

+1

Tại sao có những chỉ thị ở tất cả xem xét họ không làm bất cứ điều gì? Nếu chúng chỉ minh họa cho vấn đề, các chỉ thị này * luôn luôn * được sử dụng cùng nhau hoặc chúng có thể được sử dụng riêng biệt?Bạn có muốn chỉ thịB được chuyển đổi luôn trong tham chiếu đến phạm vi của chỉ thịA thay vì một con mới của cha/mẹ không? Tại sao directiveA có một phạm vi cô lập nhưng directiveB tuyên bố không có phạm vi mới nào cả? –

+1

@JoshDavidMiller Tôi đã thêm chiều sâu hơn một chút vào mô tả ở trên. Đối với không có phạm vi được khai báo trên 'B' và phạm vi cô lập trên' A' - tôi không có nó được thiết lập theo cách đó vì bất kỳ lý do cụ thể nào. Tất cả những gì tôi biết là tôi cần chuyển một số dữ liệu từ DOM sang chỉ thị và cách tốt nhất có vẻ là 'phạm vi: {xxx: '@'}' – jlb

Trả lời

12

Để tránh ghép nối các thành phần với nhau quá nhiều, tôi sẽ tránh sử dụng $$prevSibling. Giải pháp tốt nhất từ ​​các thành phần giống như directiveB của bạn được dự kiến ​​sẽ được sử dụng trong các thành phần directiveA là sử dụng require.

.directive('directiveB', function() { 
    return { 
    require: '^directiveA', 
    scope: true, 
    link: function (scope, element, attrs, directiveA) { 
     scope.obj = directiveA.getObj(); 
    } 
    }; 
}) 

Các ^require chỉ ra rằng ở đâu đó trên các yếu tố của chỉ thị này hoặc trên bất kỳ yếu tố trên nó trong hệ thống phân cấp DOM là một chỉ thị gọi là directiveA, và chúng tôi muốn gọi các phương thức trên bộ điều khiển của nó.

.directive('directiveA', function() { 
    return { 
    // ... 
    controller: function ($scope) { 
     // ... 
     this.getObj = function() { 
     return $scope.obj; 
     }; 
    } 
    }; 
}) 

Vì vậy, bây giờ trong directiveB bạn có thể sử dụng ng-model="obj.attr".

Có nhiều biến thể về vấn đề này, nhưng xem xét câu hỏi chung chung như thế nào, tôi cảm thấy đây là cách tiếp cận tốt nhất. Đây là một Fiddle cập nhật: http://jsfiddle.net/yugQf/7/.

+0

Trong fiddle của bạn, cô lập các thuộc tính phạm vi 'attr' và' value' không được sử dụng và do đó có thể bị loại bỏ. –

+0

@MarkRajcok - Bạn nói đúng. Họ đến từ Fiddle anh ấy đăng và anh ta chỉ ra để trả lời câu hỏi của tôi trên bài đăng của anh ấy rằng anh ấy muốn họ, nhưng họ không được sử dụng. Tôi loại bỏ chúng chỉ giống nhau để tránh nhầm lẫn. Một lần nữa, cảm ơn bạn cho lời khuyên! –

+0

Đồng hồ $ trong chỉ thịB là không cần thiết. Vì getObj() trả về một đối tượng, chỉ cần gán nó cho phạm vi của directiveB là đủ, bởi vì nó sẽ là một tham chiếu đến đối tượng trong directiveA. Vì vậy, tất cả những gì cần thiết trong hàm liên kết là 'scope.obj = directiveA.getObj();'. Trong [Fiddle] này (http://jsfiddle.net/mrajcok/ffmC6/) tôi đã sử dụng 'obj2' trong directiveB để thể hiện rõ hơn khái niệm. Ngoài ra, trong mã mẫu ở trên cho directiveB, bạn có 'scope: true', nhưng fiddle của bạn không có. Bạn thích/có ý định gì? (chỉ tò mò, nó hoạt động một trong hai cách) –

6

@Josh đề cập trong câu trả lời của ông rằng

Giải pháp tốt nhất kể từ directiveB -like thành phần của bạn được dự kiến ​​sẽ được sử dụng trong vòng directiveA thành phần là sử dụng require.

Tôi đã đùa giỡn với điều này và tôi tin rằng một bộ điều khiển trên directiveAchỉ giải pháp (do 1 Josh). Đây là những gì các phạm vi trông giống như sử dụng violon của OP: (. Đảo ngược vào mũi tên màu nâu và bạn có $$ previousSibling thay vì $$ nextSibling) scopes picture

Ngoài $$previousSibling, phạm vi 004 không có con đường để cô lập phạm vi 003.Lưu ý rằng phạm vi 004 là phạm vi được chuyển đổi mà directiveA tạo và từ directiveB không tạo phạm vi mới, phạm vi này cũng được sử dụng bởi directiveB.

Vì đối tượng bạn muốn chia sẻ với directiveB đang được tạo trong bộ điều khiển của directiveA, chúng tôi cũng không thể sử dụng thuộc tính để chia sẻ dữ liệu giữa các chỉ thị.


Tạo mô hình bên trong chỉ thị và sau đó chia sẻ mô hình đó với thế giới bên ngoài là không điển hình. Thông thường, bạn sẽ muốn xác định các mô hình của mình bên ngoài chỉ thị của bạn và thậm chí bên ngoài bộ điều khiển của bạn (listen for a few minutes to Misko). Dịch vụ thường là nơi tốt để lưu trữ các mô hình/dữ liệu của bạn. Bộ điều khiển thông thường nên tham khảo các phần của (các) mô hình cần được chiếu vào dạng xem mà chúng được liên kết với.

Để đơn giản, tôi sẽ xác định mô hình trên bộ điều khiển, sau đó các chỉ thị sẽ truy cập cả hai mô hình này theo cách thông thường. Đối với mục đích sư phạm, directiveA sẽ vẫn sử dụng phạm vi cách ly và directiveB sẽ tạo phạm vi con mới bằng cách sử dụng scope: new như trong câu trả lời của @ Josh. Nhưng bất kỳ kiểu nào (cô lập, con mới, không có phạm vi mới) và kết hợp sẽ hoạt động, bây giờ chúng ta có mô hình được định nghĩa trong một phạm vi cha mẹ.

Ctrl:

$scope.model = {value: '#33ff33', checkedState = true}; 

HTML:

<div ng-controller="NoTouchPrevSibling"> 
    <div data-directive-a data-value="model.value" data-checked="model.checkedState"> 
     <div data-directive-b></div> 
    </div> 

Vì lý do sư phạm khác, tôi đã lựa chọn để vượt qua directiveA hai thuộc tính mô hình như là thuộc tính riêng biệt, nhưng toàn bộ mô hình/đối tượng cũng có thể đã được thông qua. Vì directiveB sẽ tạo ra một phạm vi con, nó không cần truyền bất kỳ thuộc tính nào vì nó có quyền truy cập vào tất cả các thuộc tính phạm vi cha/bộ điều khiển.

Chỉ:

app.directive('directiveA', function() { 
    return { 
     template: '<div>' 
      + 'inside parent directive: {{checkedState}}' 
      + '<input type="checkbox" ng-model="checkedState" />' 
      + '<div ng-transclude></div>' 
      + '</div>', 
     transclude: true, 
     replace: true, 
     scope: { 
       value: '=', 
       checkedState: '=checked' 
      }, 
    }; 
}); 
app.directive('directiveB', function() { 
    return { 
     template: '<div>' 
      + '<span>inside transcluded directive: {{model.checkedState}}</span>' 
      + '<input type="text" ng-model="model.value" />' 
      + '</div>', 
     replace: true, 
     scope: true 
    }; 
}); 

Scopes:

scopes

Lưu ý rằng phạm vi con directiveB của (006) được thừa hưởng từ phạm vi nhúng directiveA của (005).

Sau khi nhấp vào hộp kiểm và thay đổi giá trị trong hộp văn bản:

scopes after interaction

Lưu ý rằng tay cầm Góc cập nhật các thuộc tính phạm vi cô lập. Bình thường JavaScript prototypal inheritance cho phép truy cập phạm vi con của directiveB vào model trong phạm vi bộ điều khiển (003).

Fiddle

+0

+1 Hình minh họa rất đẹp! Tôi luôn đánh giá cao các sơ đồ thừa kế mà bạn đưa vào các câu trả lời liên quan đến phạm vi của mình. –

+0

+1 Cảm ơn các biểu đồ Mark - Tôi đã chấp nhận câu trả lời của Josh như anh ta trước, nhưng đầu vào của bạn được đánh giá cao. – jlb

+1

@jlb, Josh cung cấp câu trả lời thực sự, vì vậy anh ấy chắc chắn xứng đáng chấp nhận. Tôi đã suy nghĩ về câu hỏi của bạn (xuất sắc) một số sáng nay. Nó đã làm phiền tôi rằng chúng tôi đang bị ràng buộc để sử dụng giải pháp 'require'. Tôi sẽ bổ sung thêm một số suy nghĩ (và sơ đồ) cho câu trả lời của tôi (khi tôi có thời gian). Để cung cấp cho bạn một tóm tắt nhanh chóng mặc dù: tạo ra một mô hình bên trong một chỉ thị và sau đó chia sẻ nó bên ngoài là khá không điển hình. Cách điển hình hơn là có một bộ điều khiển tham chiếu một mô hình, sau đó có thể được chia sẻ với tất cả các chỉ thị con/con cháu. –

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