有没有办法在AngularJS绑定中使用数学函数?
如。
<p>The percentage is {{Math.round(100*count/total)}}%</p>
这把小提琴说明了这个问题
http://jsfiddle.net/ricick/jtA99/1/
有没有办法在AngularJS绑定中使用数学函数?
如。
<p>The percentage is {{Math.round(100*count/total)}}%</p>
这把小提琴说明了这个问题
http://jsfiddle.net/ricick/jtA99/1/
当前回答
这是一个棘手的问题,因为你没有给出你正在做的事情的完整背景。接受的答案是可行的,但在某些情况下会导致较差的性能。这一点,而且它将更难测试。
如果你把它作为静态表单的一部分,没问题。公认的答案是有效的,即使它不容易测试,而且它很古怪。
如果你想成为“Angular”:
你需要将任何“业务逻辑”(即改变要显示的数据的逻辑)排除在视图之外。这样你就可以对你的逻辑进行单元测试,这样你就不会把控制器和视图紧密耦合起来。理论上,您应该能够将控制器指向另一个视图,并使用作用域中的相同值。(如果有道理的话)。
你还需要考虑绑定内部的任何函数调用(比如{{}}或ng-bind或ng-bind-html)都必须在每个摘要上求值,因为angular无法知道值是否发生了变化,或者是否像作用域上的属性那样。
“angular”的方法是在变化时使用ng-change事件或甚至$watch将值缓存到作用域的属性中。
例如,对于静态表单:
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>
现在您可以测试它了!
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.
});
});
其他回答
为什么不把整个数学对象包装在一个过滤器中呢?
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:'ceil'}}
虽然公认的答案是正确的,你可以注入Math来在angular中使用它,对于这个特定的问题,更传统的/angular方式是数字过滤器:
<p>The percentage is {{(100*count/total)| number:0}}%</p>
你可以在这里阅读更多关于数字过滤器的信息:http://docs.angularjs.org/api/ng/filter/number
我认为最好的方法是创建一个过滤器,就像这样:
myModule.filter('ceil', function() {
return function(input) {
return Math.ceil(input);
};
});
然后标记看起来像这样:
<p>The percentage is {{ (100*count/total) | ceil }}%</p>
更新小提琴:http://jsfiddle.net/BB4T4/
你必须将Math注入你的作用域,如果你需要使用它 $scope对数学一无所知。
你可以用最简单的方法
$scope.Math = window.Math;
在控制器中。 Angular的正确方法是创建一个Math服务。
这看起来不像是一种非常Angular的方式。我不完全确定为什么它不起作用,但您可能需要访问作用域才能使用这样的函数。
我的建议是创建一个过滤器。这就是Angular的方式。
myModule.filter('ceil', function() {
return function(input) {
return Math.ceil(input);
};
});
然后在你的HTML中这样做:
<p>The percentage is {{ (100*count/total) | ceil }}%</p>