AngularJS バインディングで数学関数を使用する方法はありますか?
例えば
<p>The percentage is {{Math.round(100*count/total)}}%</p>
このフィドルは問題を示しています
AngularJS バインディングで数学関数を使用する方法はありますか?
例えば
<p>The percentage is {{Math.round(100*count/total)}}%</p>
このフィドルは問題を示しています
数学について何も知らないMath
のでスコープを使用する必要がある場合は、スコープ
に注入する必要があります。$scope
最も簡単な方法は、あなたが行うことができます
$scope.Math = window.Math;
あなたのコントローラーで。これを正しく行うAngularの方法は、数学サービスを作成することだと思います。
あなたがしていることの完全な文脈を与えていないので、これは答えるのが難しいものです. 受け入れられた答えは機能しますが、場合によってはパフォーマンスが低下します。それは、テストするのが難しくなるでしょう。
これを静的フォームの一部として実行している場合は問題ありません。テストが簡単でなくても、受け入れられた答えは機能します。
「ビジネス ロジック」 (つまり、表示されるデータを変更するロジック) をビューから除外する必要があります。これは、ロジックを単体テストできるようにするためであり、コントローラーとビューを密結合させないようにするためです。理論的には、コントローラーを別のビューに向けて、スコープから同じ値を使用できるはずです。(それが理にかなっている場合)。
また、バインディング内の関数呼び出し ( {{}}
orng-bind
など) はすべてのダイジェストng-bind-html
で評価する必要があることも考慮する必要があります。角度には、値が変更されたかどうか、またはプロパティのように変更されたかどうかを知る方法がないためです。スコープ上。
これを行う「角度のある」方法は、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'}}
より良いオプションは、使用することです:
{{(100*score/questionCounter) || 0 | number:0}}
値が初期化されていない場合、式のデフォルト値を 0 に設定します。
Angular で簡単な計算を行う最も簡単な方法は、ページで大量の計算を行う必要がないと仮定して、必要に応じて個々のバインディングの HTML マークアップで直接行うことです。次に例を示します。
{{(data.input/data.input2)| number}}
この場合、() で計算を行ってから、フィルター | を使用します。数字の答えを得る。Angular 数値をテキストとしてフォーマットする方法の詳細は次のとおりです。
Angular で単純なラウンドを行いたい場合は、式の中に簡単にフィルターを設定できます。例えば:
{{ val | number:0 }}
他の数値フィルター オプションについては、このCodePenの例 & を参照してください。
グローバル Math オブジェクトをスコープにバインドします (window ではなく $window を使用することを忘れないでください)。
$scope.abs = $window.Math.abs;
HTML でバインディングを使用します。
<p>Distance from zero: {{abs(distance)}}</p>
または、特定の数学関数のフィルターを作成します。
module.filter('abs', ['$window', function($window) {
return function(n) {
return $window.Math.abs($window.parseInt(n));
};
});
HTML でフィルターを使用します。
<p>Distance from zero: {{distance | abs}}</p>
これは多かれ少なかれ 3 つの回答 (Sara Inés Calderón、klaxon、および Gothburz によるもの) の要約ですが、それらはすべて重要なものを追加しているため、解決策に参加してさらに説明を追加する価値があると考えています。
あなたの例を考えると、次を使用してテンプレートで計算を行うことができます。
{{ 100 * (count/total) }}
ただし、これにより小数点以下の桁数が非常に多くなる可能性があるため、フィルターを使用することをお勧めします。
{{ 100 * (count/total) | number }}
デフォルトでは、数値フィルターは最大 3 つの小数桁を残します。これは、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>
最後に、外部データ ソースに依存している場合は、適切なフォールバック値を提供することをお勧めします(そうしないと、サイトに NaN または何も表示されない場合があります)。
{{ (100 * (count/total) | number:0) || 0 }}
サイドノート: 仕様によっては、フォールバックをより正確に設定したり、既に下位レベルでフォールバックを定義したりできる場合もあります (例: {{(100 * (count || 10)/ (total || 100) | number:2)}}
)。ただし、これは常に意味があるとは限りません..
パイプを使用した 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'}}