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 对象哈希。

由于我为指令设置了一个控制器,因此我可以内联包含对该控制器范围函数的调用。

这是控制器:

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

这是修改后的 HTML,当我们包含对该$scope.getFilename函数的内联调用时(新的第二段):

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

但是,这没有用。这将只打印相同的字符串“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-* 属性?我只是想知道这是否可能。

4

3 回答 3

2

但是等等——这行不通。范围内没有变量“a”。多亏了 ng-repeat,我们可以使用内联变量,但是变量在绑定到指令的范围内不可用。

实际上变量a在与指令控制器关联的范围内。该指令创建的每个控制器都获取由 ng-repeat 迭代创建的子范围。所以这有效(注意$scope .a.id):

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

这是一个显示控制器范围、指令范围和 ngRepeat 范围的小提琴。

“如果同一元素上的多个指令请求新范围,则只会创建一个新范围。”——指令文档,“指令定义对象”部分

在您的示例中, ng-repeat 正在创建一个新范围,因此同一元素上的所有指令都获得相同的新(子)范围。

此外,如果您确实遇到需要将变量放入控制器的情况,使用属性会比使用 ng-init 更好。

于 2013-01-22T03:48:54.097 回答
2

另一种方法是使用ng-init和设置子范围的模型属性。看到这个小提琴

相关代码将是

<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';
    }
}
于 2013-01-20T06:56:18.977 回答
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';
    }
}
于 2013-01-20T06:37:02.690 回答