我想在AngularJS应用程序中添加一些实用程序功能。例如:
$scope.isNotString = function (str) {
return (typeof str !== "string");
}
这是将它们添加为服务的最佳方法吗?从我所读到的,我可以做到 这个,但后来我想在我的HTML页面中使用这些,所以它仍然可能 他们在服务?例如,我可以使用以下内容:
<button data-ng-click="doSomething()"
data-ng-disabled="isNotString(abc)">Do Something
</button>
有人能举例说明我如何添加这些内容。我应该创建一个服务 还是有其他方法可以做到这一点。最重要的是我想要这些实用程序 函数在文件中,而不是与主要设置的另一部分组合。
我知道有一些解决方案,但没有一个是如此清晰。
解决方案1 - Urban提议
$scope.doSomething = ServiceName.functionName;
这里的问题是我有20个功能和10个控制器。如果我这样做,则意味着向每个控制器添加大量代码。
解决方案2 - 由我提议
var factory = {
Setup: function ($scope) {
$scope.isNotString = function (str) {
return (typeof str !== "string");
}
这样做的缺点是,在每个控制器的开头,我会对通过$ scope的每个服务进行一次或多次这些安装调用。
解决方案3 - Urban提议
城市提出的创建通用服务的解决方案看起来不错。这是我的主要设置:
var app = angular
.module('app', ['ngAnimate', 'ui.router', 'admin', 'home', 'questions', 'ngResource', 'LocalStorageModule'])
.config(['$locationProvider', '$sceProvider', '$stateProvider',
function ($locationProvider, $sceProvider, $stateProvider) {
$sceProvider.enabled(false);
$locationProvider.html5Mode(true);
我应该将通用服务添加到此,我该怎么做?
答案 0 :(得分:105)
编辑7/1/15:
我很久以前写过这个答案,并且在一段时间内没有用角度保持很多,但似乎这个答案仍然比较受欢迎,所以我想指出一些点@nicolas以下是好的。首先,注入$ rootScope并在其中附加帮助程序将使您不必为每个控制器添加它们。另外 - 我同意如果您要添加的内容应该被视为Angular服务或过滤器,那么它们应该以这种方式被采用到代码中。
此外,从当前版本1.4.2开始,Angular公开了一个“Provider”API,允许将其注入配置块。有关更多信息,请参阅以下资源:
https://docs.angularjs.org/guide/module#module-loading-dependencies
AngularJS dependency injection of value inside of module.config
我认为我不会更新下面的实际代码块,因为这些天我并没有真正积极地使用Angular而且我真的不想冒新的答案而不觉得它确实符合新的最佳实践。如果其他人感觉到这一点,那么一定要去做吧。
编辑2/3/14:
在考虑了这个问题并阅读了其他一些答案后,我实际上认为我更喜欢@Brent Washburne和@Amogh Talpallikar提出的方法的变体。特别是如果你正在寻找像isNotString()或类似的实用程序。这里一个明显的优点是你可以在角度代码之外重复使用它们,你可以在你的配置功能中使用它们(你不能用服务做)。
话虽如此,如果你正在寻找一种通用的方法来重新使用正确的服务,我认为旧的答案仍然很好。
我现在要做的是:
app.js:
var MyNamespace = MyNamespace || {};
MyNamespace.helpers = {
isNotString: function(str) {
return (typeof str !== "string");
}
};
angular.module('app', ['app.controllers', 'app.services']).
config(['$routeProvider', function($routeProvider) {
// Routing stuff here...
}]);
controller.js:
angular.module('app.controllers', []).
controller('firstCtrl', ['$scope', function($scope) {
$scope.helpers = MyNamespace.helpers;
});
然后在你的部分你可以使用:
<button data-ng-click="console.log(helpers.isNotString('this is a string'))">Log String Test</button>
以下旧答案:
最好将它们作为服务包含在内。如果您打算在多个控制器中重复使用它们,将它们作为服务包括在内将使您不必重复代码。
如果您想在html partial中使用服务功能,那么您应该将它们添加到该控制器的范围:
$scope.doSomething = ServiceName.functionName;
然后在你的部分你可以使用:
<button data-ng-click="doSomething()">Do Something</button>
这是一种你可以保持这种有条理并且没有太多麻烦的方式:
将控制器,服务和路由代码/配置分成三个文件:controllers.js,services.js和app.js.顶层模块是“app”,它有app.controllers和app.services作为依赖项。然后app.controllers和app.services可以在他们自己的文件中声明为模块。此组织结构仅取自Angular Seed:
app.js:
angular.module('app', ['app.controllers', 'app.services']).
config(['$routeProvider', function($routeProvider) {
// Routing stuff here...
}]);
services.js:
/* Generic Services */
angular.module('app.services', [])
.factory("genericServices", function() {
return {
doSomething: function() {
//Do something here
},
doSomethingElse: function() {
//Do something else here
}
});
controller.js:
angular.module('app.controllers', []).
controller('firstCtrl', ['$scope', 'genericServices', function($scope, genericServices) {
$scope.genericServices = genericServices;
});
然后在你的部分你可以使用:
<button data-ng-click="genericServices.doSomething()">Do Something</button>
<button data-ng-click="genericServices.doSomethingElse()">Do Something Else</button>
这样,您只需向每个控制器添加一行代码,并且只要访问该范围,就可以访问任何服务函数。
答案 1 :(得分:30)
来到这个旧线程我想强调
1°)实用程序函数可以(应该?)通过module.run添加到rootscope。没有必要为此目的实例化特定的根级控制器。
angular.module('myApp').run(function($rootScope){
$rootScope.isNotString = function(str) {
return (typeof str !== "string");
}
});
2°)如果将代码组织到单独的模块中,则应使用角度services或factory,然后将它们注入传递给运行块的函数中,如下所示:
angular.module('myApp').factory('myHelperMethods', function(){
return {
isNotString: function(str) {
return (typeof str !== 'string');
}
}
});
angular.module('myApp').run(function($rootScope, myHelperMethods){
$rootScope.helpers = myHelperMethods;
});
3°)我的理解是,在视图中,对于大多数情况,您需要这些辅助函数将某种格式应用于您显示的字符串。在最后一种情况下,您需要使用有角度的filters
如果你已经将一些低级辅助方法构建到角度服务或工厂中,只需将它们注入到过滤器构造函数中:
angular.module('myApp').filter('myFilter', function(myHelperMethods){
return function(aString){
if (myHelperMethods.isNotString(aString)){
return
}
else{
// something else
}
}
);
在你看来:
{{ aString | myFilter }}
答案 2 :(得分:6)
我是否理解您只想定义一些实用工具方法并在模板中使用它们?
您不必将它们添加到每个控制器。只需为所有实用程序方法定义一个控制器,并将该控制器附加到&lt; html&gt;或者&lt; body&gt; (使用ngController指令)。您在&lt; html&gt;下的任何地方附加的任何其他控制器(意思是任何地方,期间)或&lt; body&gt; (除了&lt; head&gt;之外的任何地方)将继承该范围,并且可以访问这些方法。
答案 3 :(得分:4)
添加实用程序功能的最简单方法是将它们保留在全局级别:
function myUtilityFunction(x) { return "do something with "+x; }
然后,添加实用程序功能(到控制器)的最简单方法是将其分配给$scope
,如下所示:
$scope.doSomething = myUtilityFunction;
然后你可以这样称呼它:
{{ doSomething(x) }}
或者像这样:
ng-click="doSomething(x)"
编辑:
最初的问题是,添加效用函数的最佳方法是通过服务。我说不,如果函数足够简单(比如OP提供的isNotString()
示例)。
编写服务的好处是将其替换为另一个(通过注入)以进行测试。极端情况下,您是否需要将每个实用功能注入控制器?
文档说只是在控制器中定义行为(如$scope.double
):http://docs.angularjs.org/guide/controller
答案 4 :(得分:4)
这是一个简单,紧凑且易于理解的方法 首先,在你的js中添加一项服务。
app.factory('Helpers', [ function() {
// Helper service body
var o = {
Helpers: []
};
// Dummy function with parameter being passed
o.getFooBar = function(para) {
var valueIneed = para + " " + "World!";
return valueIneed;
};
// Other helper functions can be added here ...
// And we return the helper object ...
return o;
}]);
然后,在您的控制器中,注入您的帮助程序对象并使用任何可用的函数,如下所示:
app.controller('MainCtrl', [
'$scope',
'Helpers',
function($scope, Helpers){
$scope.sayIt = Helpers.getFooBar("Hello");
console.log($scope.sayIt);
}]);
答案 5 :(得分:1)
您也可以使用常量服务。在常量调用之外定义函数也允许它是递归的。
function doSomething( a, b ) {
return a + b;
};
angular.module('moduleName',[])
// Define
.constant('$doSomething', doSomething)
// Usage
.controller( 'SomeController', function( $doSomething ) {
$scope.added = $doSomething( 100, 200 );
})
;
答案 6 :(得分:0)
为什么不使用控制器继承,可以在ng-view内的控制器中访问HeaderCtrl范围内定义的所有方法/属性。 $ scope.servHelper可在所有控制器中访问。
angular.module('fnetApp').controller('HeaderCtrl', function ($scope, MyHelperService) {
$scope.servHelper = MyHelperService;
});
<div ng-controller="HeaderCtrl">
<div ng-view=""></div>
</div>