Có cách nào để sử dụng các hàm toán học trong các ràng buộc AngularJS không?
ví dụ
<p>The percentage is {{Math.round(100*count/total)}}%</p>
Fiddle này cho thấy vấn đề
private Math = Math;
và bạn có thể sử dụng nó.
Có cách nào để sử dụng các hàm toán học trong các ràng buộc AngularJS không?
ví dụ
<p>The percentage is {{Math.round(100*count/total)}}%</p>
Fiddle này cho thấy vấn đề
private Math = Math;
và bạn có thể sử dụng nó.
Câu trả lời:
Bạn phải đưa Math
vào phạm vi của mình, nếu bạn cần sử dụng nó như
$scope
không biết gì về Toán học.
Cách đơn giản nhất, bạn có thể làm
$scope.Math = window.Math;
trong bộ điều khiển của bạn. Cách thức góc cạnh để làm điều này một cách chính xác sẽ là tạo ra một dịch vụ Toán học, tôi đoán vậy.
formatting
, vì vậy sử dụng bộ lọc thay thế.
Mặc dù câu trả lời được chấp nhận là đúng mà bạn có thể tiêm Math
để sử dụng nó trong góc, nhưng đối với vấn đề cụ thể này, cách thông thường / góc hơn là bộ lọc số:
<p>The percentage is {{(100*count/total)| number:0}}%</p>
Bạn có thể đọc thêm về number
bộ lọc tại đây: http://docs.angularjs.org/api/ng/filter/number
{{1234.567|number:2}}
ám chỉ như 1,234.57
hoặc 1 234,57
. Nếu bạn cố gắng chuyển nó cho <input type="number" ng-value="1234.567|number:2">
bạn, sẽ làm trống đầu vào, vì giá trị KHÔNG PHẢI LÀ SỐ ĐÚNG, nhưng đại diện chuỗi phụ thuộc cục bộ.
Tôi nghĩ cách tốt nhất để làm điều đó là tạo một bộ lọc, như thế này:
myModule.filter('ceil', function() {
return function(input) {
return Math.ceil(input);
};
});
sau đó đánh dấu trông như thế này:
<p>The percentage is {{ (100*count/total) | ceil }}%</p>
Cập nhật fiddle: http://jsfiddle.net/BB4T4/
Đây là một câu hỏi để trả lời, bởi vì bạn đã không đưa ra bối cảnh đầy đủ về những gì bạn đang làm. Câu trả lời được chấp nhận sẽ hoạt động, nhưng trong một số trường hợp sẽ gây ra hiệu suất kém. Điều đó, và sẽ khó kiểm tra hơn.
Nếu bạn đang làm điều này như là một phần của một hình thức tĩnh, tốt thôi. Câu trả lời được chấp nhận sẽ hoạt động, ngay cả khi nó không dễ kiểm tra và thật khó hiểu.
Bạn sẽ muốn giữ bất kỳ "logic kinh doanh" nào (tức là logic làm thay đổi dữ liệu được hiển thị) khỏi tầm nhìn của bạn. Điều này là để bạn có thể đơn vị kiểm tra logic của mình và do đó bạn không kết hợp chặt chẽ bộ điều khiển và chế độ xem của mình. Về mặt lý thuyết, bạn sẽ có thể trỏ bộ điều khiển của mình vào một chế độ xem khác và sử dụng cùng các giá trị từ phạm vi. (nếu điều đó hợp lý).
Bạn cũng sẽ muốn xem xét rằng bất kỳ lệnh gọi hàm nào bên trong một ràng buộc (chẳng hạn như {{}}
hoặc ng-bind
hoặc ng-bind-html
) sẽ phải được đánh giá trên mỗi thông báo , bởi vì góc không có cách nào để biết giá trị đã thay đổi hay không giống như với một thuộc tính trên phạm vi.
Cách "góc cạnh" để làm điều này sẽ là lưu trữ giá trị trong một thuộc tính trên phạm vi thay đổi bằng cách sử dụng sự kiện thay đổi ng hoặc thậm chí là đồng hồ $.
Ví dụ với dạng tĩnh:
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
vì nó dường như chỉ hoạt động với kế hoạch Math.round()
?
Math
bài kiểm tra hơn. Thay vào đó, bạn có thể tạo một dịch vụ Toán học và tiêm nó.
Tại sao không bọc toàn bộ obj toán học trong một bộ lọc?
var app = angular.module('fMathFilters',[]);
function math() {
return function(input,arg) {
if(input) {
return Math[arg](input);
}
return 0;
}
}
return app.filter('math',[math]);
và sử dụng:
{{số_var | toán học: 'trần'}}
Nếu bạn đang tìm cách thực hiện một vòng đơn giản trong Angular, bạn có thể dễ dàng đặt bộ lọc bên trong biểu thức của mình. Ví dụ:
{{ val | number:0 }}
Xem ví dụ CodePen này & để biết các tùy chọn bộ lọc số khác.
Cách dễ nhất để thực hiện phép toán đơn giản với Angular là trực tiếp trong đánh dấu HTML cho các ràng buộc riêng lẻ khi cần, giả sử bạn không cần phải tính toán hàng loạt trên trang của mình. Đây là một ví dụ:
{{(data.input/data.input2)| number}}
Trong trường hợp này, bạn chỉ cần làm toán trong () và sau đó sử dụng bộ lọc | để có được một câu trả lời số. Dưới đây là thông tin thêm về định dạng Số góc dưới dạng văn bản:
Hoặc liên kết đối tượng Math toàn cầu vào phạm vi (nhớ sử dụng $ window chứ không phải window)
$scope.abs = $window.Math.abs;
Sử dụng ràng buộc trong HTML của bạn:
<p>Distance from zero: {{abs(distance)}}</p>
Hoặc tạo bộ lọc cho hàm Math cụ thể mà bạn theo đuổi:
module.filter('abs', ['$window', function($window) {
return function(n) {
return $window.Math.abs($window.parseInt(n));
};
});
Sử dụng bộ lọc trong HTML của bạn:
<p>Distance from zero: {{distance | abs}}</p>
Điều đó không giống như một cách rất góc cạnh để làm điều đó. Tôi không hoàn toàn chắc chắn tại sao nó không hoạt động, nhưng có lẽ bạn cần truy cập vào phạm vi để sử dụng một chức năng như vậy.
Đề nghị của tôi sẽ là tạo ra một bộ lọc. Đó là cách Angular.
myModule.filter('ceil', function() {
return function(input) {
return Math.ceil(input);
};
});
Sau đó, trong HTML của bạn làm điều này:
<p>The percentage is {{ (100*count/total) | ceil }}%</p>
Bộ number
lọc định dạng số với hàng nghìn dấu phân cách, vì vậy đây không hoàn toàn là một hàm toán học.
Hơn nữa, số thập phân 'giới hạn' của nó không ceil
có bất kỳ số thập phân nào được cắt nhỏ (vì một số câu trả lời khác sẽ khiến bạn tin), mà là sử dụng round
chúng.
Vì vậy, đối với bất kỳ hàm toán học nào bạn muốn, bạn có thể tiêm nó (dễ giả hơn là tiêm toàn bộ đối tượng Math) như vậy:
myModule.filter('ceil', function () {
return Math.ceil;
});
Không cần phải bọc nó trong một chức năng khác.
Đây ít nhiều là một bản tóm tắt của ba câu trả lời (của Sara Inés Calderón, klaxon và Gothburz), nhưng vì tất cả chúng đều thêm một cái gì đó quan trọng, tôi cho rằng nó đáng để tham gia các giải pháp và thêm một số giải thích.
Xem xét ví dụ của bạn, bạn có thể thực hiện các phép tính trong mẫu của mình bằng cách sử dụng:
{{ 100 * (count/total) }}
Tuy nhiên, điều này có thể dẫn đến rất nhiều vị trí thập phân, vì vậy sử dụng bộ lọc là một cách tốt để đi:
{{ 100 * (count/total) | number }}
Theo mặc định, bộ lọc số sẽ để lại tối đa ba chữ số phân số , đây là nơi đối số phân số có kích thước khá tiện dụng ( {{ 100 * (count/total) | number:fractionSize }}
), trong trường hợp của bạn sẽ là:
{{ 100 * (count/total) | number:0 }}
Điều này cũng sẽ làm tròn kết quả rồi:
Điều cuối cùng cần đề cập, nếu bạn dựa vào nguồn dữ liệu bên ngoài, có lẽ nên cung cấp giá trị dự phòng phù hợp (nếu không bạn có thể thấy NaN hoặc không có gì trên trang web của mình):
{{ (100 * (count/total) | number:0) || 0 }}
Sidenote: Tùy thuộc vào thông số kỹ thuật của bạn, bạn thậm chí có thể chính xác hơn với các dự phòng / xác định dự phòng ở các cấp thấp hơn (ví dụ {{(100 * (count || 10)/ (total || 100) | number:2)}}
). Mặc dù, điều này có thể không phải lúc nào cũng có ý nghĩa ..
Ví dụ kiểu chữ góc bằng cách sử dụng một đường ống.
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;
}
}
Thêm vào khai báo @NgModule
@NgModule({
declarations: [
MathPipe,
sau đó sử dụng trong mẫu của bạn như vậy:
{{(100*count/total) | math:'round'}}
<p>The percentage is {{(100*count/total)| number:0}}%</p>
, trong phần bình luận bên dưới.