我有这个HTML:
<p>Hello {{name}}</p>
,控制器是:
function myCtrl(scope, service) {
scope.name = service.getUsername(); // service.getUsername() return "World!"
}
myCtrl.$inject = ['$scope', 'originalService'];
服务运行正常,所以我不在这里粘贴代码...... 在这种情况下,结果是“ Hello world!” 我用这种方式更改了HTML:
<p>Hello {{service.getUsername()}}</p>
但这不起作用。
我改变了控制器:
function myCtrl(scope, service) {
scope.ser = service;
}
myCtrl.$inject = ['$scope', 'originalService'];
然后是HTML
<p>Hello {{ser.getUsername();}}</p>
这有效!
所以我的问题是:
这是直接在HTML中使用服务功能的唯一方法,还是我遗漏了什么?
答案 0 :(得分:61)
AngularJS模板只能调用范围上可用的函数。因此,无论采用何种方法,您都需要在范围内使用您的功能。
如果您希望可以从模板直接调用您的服务功能,那么您有多种选择:
您尝试过的那个 - 也就是说,在范围内公开整个服务 :
$scope.service = service;
然后在模板中:
<p>Hello {{service.getUsername();}}</p>
这是控制器中的单行程序,使范围内的所有服务方法都可用,因此也可用于模板。
逐个展示方法
准确控制暴露的内容:
$scope.getUsername = service.getUsername;
然后在模板中:
<p>Hello {{getUsername();}}</p>
这需要更多的工作暴露方法,但可以对暴露的内容进行细粒度的控制。
公开代理方法 :
$scope.getMyUsername = function() {
//pre/post processing if needed
return service.getUsername();
};
你可以使用这些方法中的任何一种,或者混合和组合它们,但是在一天结束时,一个函数必须最终在一个范围(直接或通过范围上公开的另一个对象)。
答案 1 :(得分:14)
另一种方法:
在$ rootScope上公开服务 :
$rootScope.service = service;
然后在模板中:
<p>Hello {{service.getUsername();}}</p>
您可以在app.run上执行此操作,您将在应用的所有视图中获得该服务。您可以将此方法用于身份验证服务。
答案 2 :(得分:1)
在$ scope中公开服务的另一种方法是添加一个指向服务方法/数据对象的函数指针。
scope.serviceData = service.data;
// Or
scope.getServiceData = service.getData;
在视图中,您可以使用括号调用它。
<input ng-model="serviceData().key" />
// Or
<input ng-model="getServiceData().key" />
// Or
{{getServiceData().key}}
我个人喜欢这种方法,我目前正在使用它,以使多个视图与同一数据保持同步。它确实提出了一些问题,如下所述: AngularJS. Best practice concerning proper two way data binding from a service
至于暴露于大量数据,我目前正试图做这样的事情。
// Within your view.
{{getServiceDataByKey('key')}}
// In your controller.
scope.getServiceDataByKey = service.getServiceDataByKey;
// In your service.
getServiceDataByKey : function (key) {
return dataObject[key];
}
我这样做的原因是我们希望尽可能保持控制器的清洁,并将所有数据放在一个集中的位置。此外,服务中的大多数数据都应该公开。