如何将变量注入指令的范围?

时间:2013-01-20 06:21:47

标签: angularjs

假设我有一个看起来像这样的指令:

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';
    }
}

以下是当我们对$scope.getFilename函数内联(新的第2段)进行调用时修改后的HTML:

<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- *属性?我只是想知道它是否可能。

3 个答案:

答案 0 :(得分: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';
    }
}

答案 1 :(得分:2)

  

但等等 - 这不行。范围中没有变量“a”。我们可以使用变量a inline得益于   ng-repeat,但是变量不适用于绑定的范围   指令。

实际上,变量a位于与指令控制器关联的范围内。由指令创建的每个控制器获取由ng-repeat迭代创建的子范围。这样可行(注意 $ scope .a.id):

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

这是一个显示控制器范围,指令范围和ngRepeat范围的fiddle

  

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

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

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

答案 2 :(得分: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';
    }
}