Apakah ada cara untuk menggunakan fungsi matematika di binding AngularJS?
misalnya
<p>The percentage is {{Math.round(100*count/total)}}%</p>
Biola ini menunjukkan masalahnya
private Math = Math;
dan Anda dapat menggunakannya.
Apakah ada cara untuk menggunakan fungsi matematika di binding AngularJS?
misalnya
<p>The percentage is {{Math.round(100*count/total)}}%</p>
Biola ini menunjukkan masalahnya
private Math = Math;
dan Anda dapat menggunakannya.
Jawaban:
Anda harus menyuntikkan Math
ke lingkup Anda, jika Anda perlu menggunakannya karena
$scope
tidak tahu apa-apa tentang Matematika.
Cara paling sederhana, bisa Anda lakukan
$scope.Math = window.Math;
di controller Anda. Cara sudut untuk melakukan ini dengan benar akan membuat layanan Matematika, saya kira.
formatting
, jadi gunakan filter.
Meskipun jawaban yang diterima benar bahwa Anda dapat menyuntikkan Math
untuk menggunakannya dalam sudut, untuk masalah khusus ini, cara yang lebih konvensional / sudut adalah nomor filter:
<p>The percentage is {{(100*count/total)| number:0}}%</p>
Anda dapat membaca lebih lanjut tentang number
filter di sini: http://docs.angularjs.org/api/ng/filter/number
{{1234.567|number:2}}
dirender sebagai 1,234.57
atau 1 234,57
. Jika Anda mencoba meneruskannya, <input type="number" ng-value="1234.567|number:2">
Anda akan mengosongkan input, karena nilainya BUKAN NOMOR YANG BENAR, tetapi representasi string dependen lokal.
Saya pikir cara terbaik untuk melakukannya adalah dengan membuat filter, seperti ini:
myModule.filter('ceil', function() {
return function(input) {
return Math.ceil(input);
};
});
maka markupnya terlihat seperti ini:
<p>The percentage is {{ (100*count/total) | ceil }}%</p>
Biola yang diperbarui: http://jsfiddle.net/BB4T4/
Ini adalah jawaban yang berbulu, karena Anda tidak memberikan konteks penuh dari apa yang Anda lakukan. Jawaban yang diterima akan berhasil, tetapi dalam beberapa kasus akan menyebabkan kinerja yang buruk. Itu, dan akan lebih sulit untuk diuji.
Jika Anda melakukan ini sebagai bagian dari bentuk statis, baiklah. Jawaban yang diterima akan bekerja, meskipun itu tidak mudah untuk diuji, dan itu membingungkan.
Anda harus menjaga "logika bisnis" apa pun (yaitu logika yang mengubah data yang akan ditampilkan) dari pandangan Anda. Ini agar Anda dapat menguji logika Anda, dan agar Anda tidak menyambungkan pengontrol dan tampilan Anda dengan erat. Secara teoritis, Anda harus dapat mengarahkan pengontrol Anda di tampilan lain dan menggunakan nilai yang sama dari cakupan. (jika itu masuk akal).
Anda juga harus mempertimbangkan bahwa fungsi apa pun yang memanggil bagian dalam pengikatan (seperti {{}}
atau ng-bind
atau ng-bind-html
) harus dievaluasi pada setiap intisari , karena angular tidak memiliki cara untuk mengetahui apakah nilainya telah berubah atau tidak suka dengan properti. pada ruang lingkup.
Cara "angular" untuk melakukan ini adalah dengan menyimpan nilai di properti pada lingkup perubahan menggunakan peristiwa ng-change atau bahkan $ watch.
Misalnya dengan bentuk statis:
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.
});
});
$window
karena tampaknya bekerja dengan hanya rencana Math.round()
?
Math
tes. Secara alternatif, Anda dapat membuat layanan Matematika dan menyuntikkannya.
Mengapa tidak membungkus seluruh obj matematika dalam 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]);
dan untuk menggunakan:
{{number_var | matematika: 'ceil'}}
Jika Anda ingin melakukan putaran sederhana di Angular, Anda dapat dengan mudah mengatur filter di dalam ekspresi Anda. Sebagai contoh:
{{ val | number:0 }}
Lihat contoh CodePen ini & untuk opsi filter nomor lainnya.
Cara termudah untuk melakukan matematika sederhana dengan Angular adalah langsung di markup HTML untuk binding individual sesuai kebutuhan, dengan asumsi Anda tidak perlu melakukan perhitungan massal di halaman Anda. Ini sebuah contoh:
{{(data.input/data.input2)| number}}
Dalam hal ini Anda cukup menghitung dalam () dan kemudian menggunakan filter | untuk mendapatkan nomor jawaban. Berikut ini info lebih lanjut tentang memformat angka sudut sebagai teks:
Baik mengikat objek Matematika global ke lingkup (ingat untuk menggunakan $ window bukan window)
$scope.abs = $window.Math.abs;
Gunakan penjilidan di HTML Anda:
<p>Distance from zero: {{abs(distance)}}</p>
Atau buat filter untuk fungsi Matematika spesifik yang Anda cari:
module.filter('abs', ['$window', function($window) {
return function(n) {
return $window.Math.abs($window.parseInt(n));
};
});
Gunakan filter dalam HTML Anda:
<p>Distance from zero: {{distance | abs}}</p>
Itu tidak terlihat seperti cara yang sangat Angular untuk melakukannya. Saya tidak sepenuhnya yakin mengapa itu tidak berhasil, tetapi Anda mungkin perlu mengakses ruang lingkup untuk menggunakan fungsi seperti itu.
Saran saya adalah membuat filter. Itu jalan Angular.
myModule.filter('ceil', function() {
return function(input) {
return Math.ceil(input);
};
});
Kemudian di HTML Anda lakukan ini:
<p>The percentage is {{ (100*count/total) | ceil }}%</p>
The number
Filter membentuk angka dengan pemisah ribuan, sehingga tidak ketat fungsi matematika.
Selain itu, 'limiter' desimalnya tidak ceil
berupa desimal cincang (karena beberapa jawaban lain akan membuat Anda percaya), tetapi sebaliknya round
.
Jadi untuk fungsi matematika yang Anda inginkan, Anda dapat menyuntikkannya (lebih mudah untuk mengejek daripada menyuntikkan seluruh objek Matematika) seperti:
myModule.filter('ceil', function () {
return Math.ceil;
});
Tidak perlu membungkusnya di fungsi lain juga.
Ini kurang lebih adalah ringkasan dari tiga jawaban (oleh Sara Inés Calderón, klaxon dan Gothburz), tetapi karena mereka semua menambahkan sesuatu yang penting, saya menganggapnya layak untuk bergabung dengan solusi dan menambahkan beberapa penjelasan lebih lanjut.
Mempertimbangkan contoh Anda, Anda dapat melakukan perhitungan dalam template Anda menggunakan:
{{ 100 * (count/total) }}
Namun, ini dapat menghasilkan banyak tempat desimal, jadi menggunakan filter adalah cara yang baik:
{{ 100 * (count/total) | number }}
Secara default, filter angka akan meninggalkan hingga tiga digit fraksional , di sinilah argumen fractionSize sangat berguna ( {{ 100 * (count/total) | number:fractionSize }}
), yang dalam kasus Anda adalah:
{{ 100 * (count/total) | number:0 }}
Ini juga akan melengkapi hasilnya:
Hal terakhir yang disebutkan, jika Anda mengandalkan sumber data eksternal, mungkin merupakan praktik yang baik untuk memberikan nilai cadangan yang tepat (jika tidak, Anda mungkin melihat NaN atau tidak sama sekali di situs Anda):
{{ (100 * (count/total) | number:0) || 0 }}
Sidenote: Tergantung pada spesifikasi Anda, Anda bahkan mungkin dapat lebih tepat dengan fallback Anda / tentukan fallback pada level yang lebih rendah (mis {{(100 * (count || 10)/ (total || 100) | number:2)}}
.). Padahal, ini mungkin tidak selalu masuk akal ..
Contoh skrip Angular menggunakan pipa.
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;
}
}
Tambahkan ke deklarasi @NgModule
@NgModule({
declarations: [
MathPipe,
kemudian gunakan di template Anda seperti ini:
{{(100*count/total) | math:'round'}}
<p>The percentage is {{(100*count/total)| number:0}}%</p>
lebih banyak komentar di bawah ini.