มีวิธีใช้ฟังก์ชันคณิตศาสตร์ในการโยง AngularJS หรือไม่?
เช่น
<p>The percentage is {{Math.round(100*count/total)}}%</p>
ซอนี้แสดงให้เห็นถึงปัญหา
private Math = Math;
และคุณสามารถใช้งานได้
มีวิธีใช้ฟังก์ชันคณิตศาสตร์ในการโยง AngularJS หรือไม่?
เช่น
<p>The percentage is {{Math.round(100*count/total)}}%</p>
ซอนี้แสดงให้เห็นถึงปัญหา
private Math = Math;
และคุณสามารถใช้งานได้
คำตอบ:
คุณต้องฉีดMath
เข้าไปในขอบเขตของคุณถ้าคุณจำเป็นต้องใช้มันเท่าที่
$scope
รู้เรื่องคณิตศาสตร์
วิธีที่ง่ายที่สุดคุณสามารถทำได้
$scope.Math = window.Math;
ในตัวควบคุมของคุณ วิธีการทำสิ่งที่ถูกต้องเชิงมุมคือการสร้างบริการคณิตศาสตร์ฉันเดา
formatting
ดังนั้นใช้ตัวกรองแทน
ในขณะที่คำตอบที่ยอมรับนั้นถูกต้องที่คุณสามารถฉีดMath
เพื่อใช้ในเชิงมุมสำหรับปัญหาเฉพาะนี้วิธีการทั่วไป / เชิงมุมที่มากกว่าคือตัวกรองตัวเลข:
<p>The percentage is {{(100*count/total)| number:0}}%</p>
คุณสามารถอ่านเพิ่มเติมเกี่ยวกับnumber
ตัวกรองได้ที่นี่: http://docs.angularjs.org/api/ng/filter/number
{{1234.567|number:2}}
แสดงผลเป็นหรือ1,234.57
1 234,57
หากคุณพยายามที่จะส่งผ่านไปยัง<input type="number" ng-value="1234.567|number:2">
คุณจะว่างเปล่าใส่เพราะค่าไม่ใช่จำนวนที่ถูกต้อง แต่เป็นตัวแทนสตริงขึ้นอยู่กับสถานที่
ฉันคิดว่าวิธีที่ดีที่สุดคือการสร้างตัวกรองเช่นนี้:
myModule.filter('ceil', function() {
return function(input) {
return Math.ceil(input);
};
});
ดังนั้นมาร์กอัปจะเป็นดังนี้:
<p>The percentage is {{ (100*count/total) | ceil }}%</p>
ซอที่อัปเดต: http://jsfiddle.net/BB4T4/
นี่เป็นคำตอบที่มีขนดกเพราะคุณไม่ได้ให้บริบทที่เต็มไปด้วยสิ่งที่คุณทำ คำตอบที่ยอมรับจะใช้งานได้ แต่ในบางกรณีอาจทำให้ประสิทธิภาพต่ำ นั่นและมันจะยากกว่าที่จะทดสอบ
หากคุณทำสิ่งนี้เป็นส่วนหนึ่งของรูปแบบคงที่ดี คำตอบที่ได้รับการยอมรับจะใช้ได้แม้ว่ามันจะไม่ใช่เรื่องง่ายที่จะทดสอบ
คุณจะต้องการให้ "ตรรกะทางธุรกิจ" (เช่นตรรกะที่เปลี่ยนแปลงข้อมูลที่จะแสดง) จากมุมมองของคุณ นี่คือเพื่อให้คุณสามารถหน่วยทดสอบตรรกะของคุณและเพื่อให้คุณไม่จบการมีเพศสัมพันธ์ควบคุมและมุมมองของคุณ ในทางทฤษฎีคุณควรจะสามารถชี้คอนโทรลเลอร์ของคุณไปยังมุมมองอื่นและใช้ค่าเดียวกันจากขอบเขต (ถ้ามันสมเหตุสมผล)
คุณจะต้องพิจารณาด้วยว่าการเรียกฟังก์ชั่นใด ๆ ที่อยู่ภายในการเชื่อมโยง (เช่น{{}}
หรือng-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.
});
});
$window
เพราะดูเหมือนว่าจะทำงานกับแผนเพียงMath.round()
?
Math
ทดสอบได้ง่ายขึ้น ในทางกลับกันคุณสามารถสร้างบริการคณิตศาสตร์และฉีดได้
ทำไมไม่รวม obj ทางคณิตศาสตร์ทั้งหมดลงในตัวกรอง
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 | คณิตศาสตร์: 'ceil'}}
ตัวเลือกที่ดีกว่าคือการใช้:
{{(100*score/questionCounter) || 0 | number:0}}
มันตั้งค่าเริ่มต้นของสมการที่ 0 ในกรณีที่เมื่อค่าไม่ได้เริ่มต้น
หากคุณต้องการทำรอบง่ายๆใน Angular คุณสามารถตั้งค่าตัวกรองภายในนิพจน์ของคุณได้อย่างง่ายดาย ตัวอย่างเช่น:
{{ val | number:0 }}
ดูตัวอย่างCodePenนี้& สำหรับตัวเลือกตัวกรองตัวเลขอื่น ๆ
วิธีที่ง่ายที่สุดในการทำคณิตศาสตร์อย่างง่ายด้วย Angular นั้นอยู่ใน markup HTML โดยตรงสำหรับการผูกแต่ละครั้งตามที่ต้องการโดยสมมติว่าคุณไม่จำเป็นต้องทำการคำนวณจำนวนมากบนหน้าเว็บของคุณ นี่คือตัวอย่าง:
{{(data.input/data.input2)| number}}
ในกรณีนี้คุณเพียงแค่ทำคณิตศาสตร์ใน () แล้วใช้ตัวกรอง | เพื่อรับคำตอบตัวเลข นี่คือข้อมูลเพิ่มเติมเกี่ยวกับการจัดรูปแบบตัวเลขเชิงมุมเป็นข้อความ:
ผูกวัตถุคณิตศาสตร์ระดับโลกเข้ากับขอบเขต (อย่าลืมใช้ $ 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>
นั่นดูไม่เหมือนวิธีเชิงมุมในการทำมัน ฉันไม่แน่ใจทั้งหมดว่าทำไมมันใช้งานไม่ได้ แต่คุณอาจต้องเข้าถึงขอบเขตเพื่อใช้ฟังก์ชันเช่นนั้น
คำแนะนำของฉันคือการสร้างตัวกรอง นั่นคือวิธีการเชิงมุม
myModule.filter('ceil', function() {
return function(input) {
return Math.ceil(input);
};
});
จากนั้นใน HTML ให้ทำดังนี้
<p>The percentage is {{ (100*count/total) | ceil }}%</p>
number
กรองรูปแบบจำนวนที่มีหลายพันตัวคั่นดังนั้นจึงไม่เคร่งครัดฟังก์ชั่นทางคณิตศาสตร์
นอกจากนี้ยังมีทศนิยมของ 'จำกัด' ไม่ceil
สับใด ๆ ทศนิยม (เป็นคำตอบอื่น ๆ บางคนจะนำคุณไปสู่เชื่อว่า) แต่round
ไอเอ็นจีพวกเขา
ดังนั้นสำหรับฟังก์ชั่นคณิตศาสตร์ใด ๆ ที่คุณต้องการคุณสามารถฉีด (เยาะเย้ยได้ง่ายกว่าการฉีดวัตถุคณิตศาสตร์ทั้งหมด) ดังนี้:
myModule.filter('ceil', function () {
return Math.ceil;
});
ไม่จำเป็นต้องห่อในฟังก์ชั่นอื่นเช่นกัน
นี่เป็นบทสรุปสั้น ๆ ของคำตอบสามข้อ (โดย Sara InésCalderón, klaxon และ Gothburz) แต่เมื่อพวกเขาเพิ่มสิ่งที่สำคัญฉันคิดว่ามันคุ้มค่าที่จะเข้าร่วมโซลูชั่นและเพิ่มคำอธิบายเพิ่มเติม
เมื่อพิจารณาตัวอย่างของคุณคุณสามารถทำการคำนวณในแม่แบบของคุณโดยใช้:
{{ 100 * (count/total) }}
อย่างไรก็ตามการทำเช่นนี้อาจส่งผลให้เกิดทศนิยมจำนวนมากดังนั้นการใช้ตัวกรองจึงเป็นวิธีที่ดี
{{ 100 * (count/total) | number }}
ตามค่าเริ่มต้นตัวกรองตัวเลขจะมีตัวเลขเศษส่วนได้ถึงสามหลักซึ่งเป็นที่ที่อาร์กิวเมนต์ fractionSizeมีประโยชน์มาก ( {{ 100 * (count/total) | number:fractionSize }}
) ซึ่งในกรณีของคุณจะเป็น:
{{ 100 * (count/total) | number:0 }}
ซึ่งจะเป็นการปัดเศษผลลัพธ์แล้ว:
สิ่งสุดท้ายที่ต้องพูดถึงถ้าคุณพึ่งพาแหล่งข้อมูลภายนอกเป็นวิธีที่ดีที่จะให้ค่าทางเลือกที่เหมาะสม(ไม่เช่นนั้นคุณอาจเห็น NaN หรือไม่มีอะไรในไซต์ของคุณ):
{{ (100 * (count/total) | number:0) || 0 }}
Sidenote: ขึ้นอยู่กับข้อกำหนดของคุณคุณอาจจะแม่นยำยิ่งขึ้นเมื่อใช้ทางเลือก / กำหนดทางเลือกในระดับที่ต่ำกว่าอยู่แล้ว (เช่น{{(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'}}
<p>The percentage is {{(100*count/total)| number:0}}%</p>
เพิ่มเติมในความคิดเห็นด้านล่าง