AngularJS元素的子范围

时间:2015-04-14 17:24:41

标签: angularjs

我有一个名为profile.html的可重用模板。它看起来像这样:

<div>
  {{firstName}}

</div>

我将它嵌入另一个绑定到专用控制器的模板中:

<div ng-include src="'templates/profile.html'"></div>

我想为这个div创建一个子$ scope。在父模板的控制器中,我有类似的内容:

$scope.profile = theProfile;

我希望profile.html模板的子范围是父$ scope.profile。类似于:

<div ng-include src="'templates/profile.html'" ng-scope="{{profile}}"></div>

我该怎么做?

2 个答案:

答案 0 :(得分:1)

看起来你基本上是通过尝试设置模板和范围来重新发明指令。此外,$ scope是一个对象,上面有大量其他属性/对象,因此将其设置为另一个对象会有问题。

如果您真的想这样做,下面将创建一个指令,使用角度副本将传入的profile合并到$scope。我建议只使用$ scope.profile。

.directive('profile', [function(){
    return{
        templateUrl:'templates/profile.html',
        scope:{profile:'='},
        controller: function($scope){
            angular.copy($scope.profile, $scope) // if you really, really want the properties right on the scope.

        }
    }
}] 

答案 1 :(得分:1)

ngInclude会自动创建子范围。您不应该显式地将一些数据传递给它,因为它可以通过原型继承访问其父作用域(如果您的模板更改了作用域,这可能会成为一个问题)。

这里的问题是您的模板需要在范围内存在firstName属性,但它并不存在。因此,您可以将模板更改为

<div>
  {{profile.firstName}}
</div>

但是这会将模板耦合到profile对象,这可能是一个坏主意。

另一种解决方案是在正确的范围内手动创建firstName属性:

<div ng-include src="'templates/profile.html'" 
     ng-init="firstName=profile.firstName">
</div>

我不太喜欢这个解决方案,因为如果模板需要更多属性并且它在某种程度上打破了模板封装,它很容易失控。

最后,您可以将该模板包装在指令中:

directive('whateverMakesSense', function() {
    return {
        restrict: 'E',
        template: '<div>{{data.firstName}}</div>',
        scope: { data: '=' }        
    };
});

...

<whatever-makes-sense data="profile"></whatever-makes-sense>

如果您发现自己在很多地方使用该模板,我建议您选择自定义指令方法。它会给你更多的控制,事情会更好地封装,作为奖励你的标记会更加语义 - 当然,如果你使用whatever-makes-sense以外的任何东西。 :)