2013-01-20 57 views
5

比方說,我有一個指令,它看起來像這樣:如何將一個變量注入指令的作用域?

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

這意味着我可以寫這樣的「附件」元素的列表:

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

在上面的代碼中,我們假設note.getAttachments()返回一組簡單的JavaScript對象散列。

因爲我爲該指令設置了一個控制器,所以我可以在內聯中包含對該控制器的作用域函數的調用。

這裏的控制器:

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

然而,這ISN:

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

這裏是因爲當我們包括對$scope.getFilename內聯函數的調用(新的第2段)修改後的HTML沒有用處。這將只打印相同的字符串「image.jpg」作爲每個附件的文件名。

實際上,附件的文件名基於附件ID。所以ID爲「2」的附件的文件名爲「image-2.jpg」。

所以我們的getFilename功能需要修改。讓我們來解決它:

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

別急—這是不行的。範圍內沒有變量a。我們可以使用變量a內嵌感謝ng-repeat,但a變量不可用於綁定到該指令的範圍。

所以問題是,我該如何使a可用的範圍?

請注意:我知道在這個特定的例子中,我可以直接打印image-{{a.id}}.jpg。但是這並沒有回答這個問題。這只是一個非常簡單的例子。實際上,getFilename功能太複雜,無法在線打印。

編輯:是的,getFilename可以接受一個參數,這將工作。但是,這也不能回答這個問題。我仍然想知道,是否可以在不使用內聯的情況下將a納入範圍。

例如,也許有一種方法可以直接注射到控制器,以便將它寫成:

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

但我哪裏會在傳遞的呢?有什麼我可以添加到指令聲明?也許我可以在ng-repeat旁添加ng- *屬性?我只想知道這是否可能。

+0

你不能'getFilename'接受一個參數嗎? – dokkaebi

+0

'$ scope.getFilename = function(a){return'image-'+ a.id +'.jpg'; }',然後'附件文件名:{{getFilename(a)}}' – dokkaebi

回答

2

但等待 - 這是不行的。範圍內沒有變量「a」。我們可以使用內聯變量a,這要歸功於 ng-repeat,但是一個變量不適用於綁定到 指令的範圍。

實際上可變a與指令控制器相關聯的範圍。由指令創建的每個控制器都獲取由ng-repeat迭代創建的子範圍。所以這個工作(注意$範圍 .a.id):

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

這裏有一個fiddle,顯示控制器範圍內,指導範圍,並ngRepeat作用域。

「如果同一個元素上的多個指令,要求新的範圍,只有一個新的範圍被創建。」 - Directive docs,部分「指令定義對象」

在你的榜樣,NG-重複是創建一個新的範圍,所以同一元素上的所有指令都會得到同樣的新(子)範圍。另外,如果您遇到過需要將變量放入控制器的情況,使用屬性會比使用ng-init更好。

+0

感謝您指出這一點。我想這是更正確的答案。 'ng-init'有助於將範圍內的'a'重命名爲更具描述性的內容,但'$ scope.a'實際上已經可用了,我可以使用它。 – cilphex

0

只要將它傳遞到你的函數。

查看:

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

控制器

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

另一種方法是使用ng-init併爲孩子作用域的模型屬性。看到這個fiddle

相關的代碼將

<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'; 
    } 
} 
相關問題