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

如。

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

这把小提琴说明了这个问题

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


当前回答

使用管道的Angular Typescript示例。

math.pipe.ts

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'math',
})

export class MathPipe implements PipeTransform {

  transform(value: number, args: any = null):any {
      if(value) {
        return Math[args](value);
      }
      return 0;
  }
}

添加到@NgModule声明中

@NgModule({
  declarations: [
    MathPipe,

然后在模板中像这样使用:

{{(100*count/total) | math:'round'}}

其他回答

这是一个棘手的问题,因为你没有给出你正在做的事情的完整背景。接受的答案是可行的,但在某些情况下会导致较差的性能。这一点,而且它将更难测试。

如果你把它作为静态表单的一部分,没问题。公认的答案是有效的,即使它不容易测试,而且它很古怪。

如果你想成为“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.
  });
});

使用管道的Angular Typescript示例。

math.pipe.ts

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'math',
})

export class MathPipe implements PipeTransform {

  transform(value: number, args: any = null):any {
      if(value) {
        return Math[args](value);
      }
      return 0;
  }
}

添加到@NgModule声明中

@NgModule({
  declarations: [
    MathPipe,

然后在模板中像这样使用:

{{(100*count/total) | math:'round'}}

数字过滤器使用数千个分隔符格式化数字,因此它不是严格意义上的数学函数。

此外,它的小数“限制器”并没有限制任何小数(正如其他一些答案会让你相信的那样),而是四舍五入。

因此,对于任何你想要的数学函数,你可以像这样注入它(模仿比注入整个math对象更容易):

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

也不需要将它包装在另一个函数中。

我认为最好的方法是创建一个过滤器,就像这样:

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

然后标记看起来像这样:

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

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

更好的选择是使用:

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

在值未初始化的情况下,它将方程的默认值设置为0。