2013-01-20 26 views
5

Hãy nói rằng tôi đã có một chỉ thị mà trông như thế này:Làm cách nào để đưa biến vào phạm vi của chỉ thị?

directive('attachment', function() { 
    return { 
     restrict: 'E', 
     controller: 'AttachmentCtrl' 
    } 
}) 

Điều đó có nghĩa tôi có thể viết một danh sách các yếu tố 'đính kèm' như thế này:

<attachment ng-repeat="a in note.getAttachments()"> 
    <p>Attachment ID: {{a.id}}</p> 
</attachment> 

Trong đoạn trên, chúng ta hãy giả sử rằng note.getAttachments() trả về một tập hợp các băm đối tượng javascript đơn giản.

Vì tôi đặt bộ điều khiển cho chỉ thị, tôi có thể bao gồm các cuộc gọi đến các chức năng phạm vi của bộ điều khiển đó.

Dưới đây là bộ điều khiển:

function AttachmentCtrl($scope) { 
    $scope.getFilename = function() { 
     return 'image.jpg'; 
    } 
} 

Và đây là HTML sửa đổi cho khi chúng ta bao gồm một lời kêu gọi mà $scope.getFilename chức năng inline (thứ 2 đoạn mới):

<attachment ng-repeat="a in note.getAttachments()"> 
    <p>Attachment ID: {{a.id}}</p> 
    <p>Attachment file name: {{getFilename()}} 
</attachment> 

Tuy nhiên, isn này không hữu ích. Điều này sẽ chỉ in cùng một chuỗi, "image.jpg", làm tên tệp cho mỗi tệp đính kèm.

Trong thực tế, tên tệp cho tệp đính kèm dựa trên ID tệp đính kèm. Vì vậy, tệp đính kèm có ID là "2" sẽ có tên tệp là "image-2.jpg".

Vì vậy, cần chỉnh sửa getFilename chức năng của chúng tôi. Hãy sửa lỗi:

function AttachmentCtrl($scope) { 
    $scope.getFilename = function() { 
     return 'image-' + a.id + '.jpg'; 
    } 
} 

Nhưng đợi — việc này sẽ không hoạt động. Không có biến số a trong phạm vi. Chúng tôi có thể sử dụng biến số a nội tuyến nhờ vào số ng-repeat, nhưng biến số a không có sẵn cho phạm vi được ràng buộc với chỉ thị.

Vì vậy, câu hỏi đặt ra là, làm cách nào để làm cho số đó a khả dụng cho phạm vi?

Xin lưu ý: Tôi nhận thấy rằng trong ví dụ cụ thể này, tôi chỉ có thể in image-{{a.id}}.jpg nội tuyến. Nhưng điều đó không trả lời câu hỏi. Đây chỉ là một ví dụ cực kỳ đơn giản. Trong thực tế, hàm getFilename sẽ là một thứ quá phức tạp để in nội tuyến.

Chỉnh sửa: Có, getFilename có thể chấp nhận một đối số và điều đó sẽ hoạt động. Tuy nhiên, điều đó cũng không trả lời câu hỏi. Tôi vẫn muốn biết, mà không có cách giải quyết, cho dù bạn có thể nhận được a vào phạm vi mà không sử dụng nội tuyến.

Ví dụ, có thể có một cách để tiêm trực tiếp vào bộ điều khiển nên nó sẽ được viết như sau:

function AttachmentCtrl($scope, a) { ... } 

Nhưng nơi tôi sẽ vượt qua nó trong từ đâu? Có điều gì tôi có thể thêm vào tuyên bố chỉ thị? Có lẽ một thuộc tính mà tôi có thể thêm vào bên cạnh ng-repeat? Tôi chỉ muốn biết nếu nó có thể.

+0

Bạn không thể 'getFilename' chấp nhận một đối số? – dokkaebi

+0

'$ scope.getFilename = function (a) {return 'image-' + a.id + '.jpg'; } ', và sau đó' Tên tệp đính kèm: {{getFilename (a)}} ' – dokkaebi

Trả lời

2

Nhưng chờ đợi - điều này sẽ không làm việc. Không có biến "a" trong phạm vi. Chúng tôi có thể sử dụng biến nội tuyến nhờ số ng-lặp lại, nhưng một biến không có sẵn cho phạm vi được ràng buộc để chỉ thị.

Biến thực tế a nằm trong phạm vi kết hợp với bộ điều khiển chỉ thị. Mỗi bộ điều khiển được tạo ra bởi chỉ thị nhận phạm vi con được tạo bởi lặp lại ng-lặp lại. Vì vậy, các công trình này (lưu ý $ phạm vi .a.id):

function AttachmentCtrl($scope) { 
    $scope.getFilename = function() { 
     return 'image-' + $scope.a.id + '.jpg'; 
} 

Dưới đây là một fiddle cho thấy phạm vi điều khiển, phạm vi chỉ thị, và ngRepeat Scopes.

"Nếu có nhiều chỉ thị trên cùng một nguyên tố yêu cầu phạm vi mới, chỉ có một phạm vi mới được tạo ra." - Directive docs, phần "Chỉ Definition Object"

Trong ví dụ của bạn, ng-repeat là tạo ra một phạm vi mới, vì vậy tất cả các chỉ thị trên cùng một phần tử đều nhận được cùng một phạm vi (con) mới.

Ngoài ra, nếu bạn từng gặp một trường hợp mà bạn cần phải nhận một biến vào bộ điều khiển, việc sử dụng các thuộc tính sẽ tốt hơn sử dụng ng-init.

+0

Cảm ơn bạn đã chỉ ra điều này. Tôi đoán đây là câu trả lời đúng hơn. 'ng-init' rất hữu ích cho việc đổi tên viết tắt' a' thành một cái gì đó có tính mô tả hơn trong phạm vi, nhưng '$ scope.a' thực sự đã sẵn sàng, và tôi có thể sử dụng nó. – cilphex

0

Chỉ cần chuyển nó vào chức năng của bạn.

Xem:

<attachment ng-repeat="a in note.getAttachments()"> 
    <p>Attachment ID: {{ a.id }}</p> 
    <p>Attachment file name: {{ getFilename(a) }} 
</attachment> 

khiển:

function AttachmentCtrl ($scope) { 
    $scope.getFilename = function (a) { 
     return 'image-' + a.id + '.jpg'; 
    } 
} 
2

Một cách khác là sử dụng ng-init và thiết lập thuộc tính mô hình cho phạm vi nhỏ. Xem fiddle

mã có liên quan này sẽ

<div ng-app='myApp' ng-controller='MyCtrl'> 
    <attachment ng-repeat="a in attachments" ng-init='model=a'> 
     <p>Attachment ID: {{model.id}}</p> 
     <p>Attachment file name: {{getFilename()}}</p> 
    </attachment> 
</div> 

function AttachmentCtrl($scope) { 
    $scope.getFilename = function() { 
     return 'image-' + $scope.model.id + '.jpg'; 
    } 
} 
Các vấn đề liên quan