在AngularJS绑定中的math函数

有没有办法在AngularJS绑定中使用math函数?

例如

<p>The percentage is {{Math.round(100*count/total)}}%</p> 

这小提琴显示问题

http://jsfiddle.net/ricick/jtA99/1/

你必须注入Math到你的范围,如果你需要使用它,因为$scope对math一无所知。

最简单的方法,你可以做

 $scope.Math = window.Math; 

在你的控制器。 正确地做到这一点的angular度将创build一个math服务,我猜。

虽然接受的答案是正确的,你可以注入Math使用angular度,对于这个特定的问题,更传统的/angular度的方式是数字filter:

 <p>The percentage is {{(100*count/total)| number:0}}%</p> 

您可以在这里阅读更多关于numberfilter的信息: http : //docs.angularjs.org/api/ng/filter/number

我认为最好的方法是创build一个filter,如下所示:

 myModule.filter('ceil', function() { return function(input) { return Math.ceil(input); }; }); 

那么标记看起来像这样:

 <p>The percentage is {{ (100*count/total) | ceil }}%</p> 

更新小提琴: http : //jsfiddle.net/BB4T4/

这是一个很好的答案,因为你没有给出你正在做的事情的完整背景。 被接受的答案将起作用,但在某些情况下会导致性能不佳。 那样的话,testing会更困难。

如果你这样做是静态表单的一部分,那很好。 即使不容易testing,被接受的答案也会起作用,而且这很容易。

如果你想成为这样的“angular”:

你会想保留任何“业务逻辑”(即改变数据显示的逻辑)。 这样你就可以对你的逻辑进行unit testing,所以你最终不会把你的控制器和你的视图紧密结合起来。 理论上,您应该能够将您的控制器指向另一个视图,并使用范围中的相同值。 (如果这是有道理的)。

您还需要考虑绑定内部的任何函数调用(如{{}}ng-bindng-bind-html )都必须在每个摘要上进行评估,因为angular度无法知道是否价值已经改变,或者不像在范围上的属性那样。

这样做的“angular度”方法是使用ng-change事件甚至$ watch来caching更改范围内属性的值。

例如用一个静态的forms:

 angular.controller('MainCtrl', function($scope, $window) { $scope.count = 0; $scope.total = 1; $scope.updatePercentage = function () { $scope.percentage = $window.Math.round((100 * $scope.count) / $scope.total); }; }); 
 <form name="calcForm"> <label>Count <input name="count" ng-model="count" ng-change="updatePercentage()" type="number" min="0" required/></label><br/> <label>Total <input name="total" ng-model="total" ng-change="updatePercentage()" type="number" min="1" required/></label><br/> <hr/> Percentage: {{percentage}} </form> 

现在你可以testing它!

 describe('Testing percentage controller', function() { var $scope = null; var ctrl = null; //you need to indicate your module in a test beforeEach(module('plunker')); beforeEach(inject(function($rootScope, $controller) { $scope = $rootScope.$new(); ctrl = $controller('MainCtrl', { $scope: $scope }); })); it('should calculate percentages properly', function() { $scope.count = 1; $scope.total = 1; $scope.updatePercentage(); expect($scope.percentage).toEqual(100); $scope.count = 1; $scope.total = 2; $scope.updatePercentage(); expect($scope.percentage).toEqual(50); $scope.count = 497; $scope.total = 10000; $scope.updatePercentage(); expect($scope.percentage).toEqual(5); //4.97% rounded up. $scope.count = 231; $scope.total = 10000; $scope.updatePercentage(); expect($scope.percentage).toEqual(2); //2.31% rounded down. }); }); 

更好的select是使用:

 {{(100*score/questionCounter) || 0 | number:0}} 

在未初始化的情况下,将公式的默认值设置为0。

假设您不需要在页面上进行批量计算,那么使用Angular进行简单math运算最简单的方法就是根据需要直接在单个绑定的HTML标记中。 这是一个例子:

 {{(data.input/data.input2)| number}} 

在这种情况下,你只需在()中做math运算,然后使用filter| 得到一个数字答案。 这里有更多关于格式化Angular数字的信息:

https://docs.angularjs.org/api/ng/filter

如果你想在Angular中做一个简单的循环,你可以很容易的在expression式中设置filter。 例如:

{{ val | number:0 }}

看到这个CodePen例子&其他数字filter选项。

有关使用数字filter的angular度文档

为什么不把整个mathobj包装在filter中?

 var app = angular.module('fMathFilters',[]); function math() { return function(input,arg) { if(input) { return Math[arg](input); } return 0; } } return app.filter('math',[math]); 

并使用:

{{number_var | math: '小区'}}

将全局math对象绑定到作用域上(记得使用$ window not window)

 $scope.abs = $window.Math.abs; 

在HTML中使用绑定:

 <p>Distance from zero: {{abs(distance)}}</p> 

或者为您所在的特定math函数创build一个filter:

 module.filter('abs', ['$window', function($window) { return function(n) { return $window.Math.abs($window.parseInt(n)); }; }); 

在HTML中使用filter:

 <p>Distance from zero: {{distance | abs}}</p> 

这看起来不是一个非常有angular度的做法。 我不完全确定为什么它不起作用,但你可能需要访问范围才能使用这样的function。

我的build议是创build一个filter。 这是angular度的方式。

 myModule.filter('ceil', function() { return function(input) { return Math.ceil(input); }; }); 

然后在你的HTML中这样做:

 <p>The percentage is {{ (100*count/total) | ceil }}%</p> 

这或多或less地是对三个答案的总结(SaraInésCalderón,klaxon和Gothburz),但是他们都增加了一些重要的东西,所以我认为值得join解决scheme并增加一些解释。

考虑你的例子,你可以在你的模板中进行计算:

 {{ 100 * (count/total) }} 

但是,这可能会导致很多小数位,所以使用filter是一个好方法:

 {{ 100 * (count/total) | number }} 

默认情况下,数字filter最多可以留下三个小数位 ,这就是fractionSize参数非常方便的地方( {{ 100 * (count/total) | number:fractionSize }} ),在你的情况下,

 {{ 100 * (count/total) | number:0 }} 

这也将结果四舍五入:

 angular.module('numberFilterExample', []) .controller('ExampleController', ['$scope', function($scope) { $scope.val = 1234.56789; } ]); 
 <!doctype html> <html lang="en"> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> </head> <body ng-app="numberFilterExample"> <table ng-controller="ExampleController"> <tr> <td>No formatting:</td> <td> <span>{{ val }}</span> </td> </tr> <tr> <td>3 Decimal places:</td> <td> <span>{{ val | number }}</span> (default) </td> </tr> <tr> <td>2 Decimal places:</td> <td><span>{{ val | number:2 }}</span></td> </tr> <tr> <td>No fractions: </td> <td><span>{{ val | number:0 }}</span> (rounded)</td> </tr> </table> </body> </html> 

numberfilter使用千位分隔符来格式化数字,所以它不是一个严格的math函数。

此外,它的小数“限制器”不会把任何一个小数点(如其他答案会让你相信),而是把它们round

所以对于你想要的任何math函数,你可以注入它(比注入整个Math对象更容易模拟),如下所示:

 myModule.filter('ceil', function () { return Math.ceil; }); 

无需将其包装在另一个function中。