Есть ли способ использовать математические функции в привязках 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
) должны оцениваться при каждом дайджесте , потому что 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.
});
});
$window
что, кажется, работает только с планом Math.round()
?
Math
тесты. С другой стороны, вы можете создать математический сервис и внедрить его.
Почему бы не обернуть весь математический объект в фильтр?
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'}}
Если вы хотите сделать простой раунд в Angular, вы можете легко установить фильтр внутри вашего выражения. Например:
{{ val | number:0 }}
Посмотрите этот пример CodePen & для других параметров фильтра чисел.
Самый простой способ сделать простую математику с Angular - это непосредственно в HTML-разметке для отдельных привязок по мере необходимости, при условии, что вам не нужно делать массовые вычисления на своей странице. Вот пример:
{{(data.input/data.input2)| number}}
В этом случае вы просто делаете математику в (), а затем используете фильтр | чтобы получить числовой ответ. Вот больше информации о форматировании угловых чисел как текста:
Либо привяжите глобальный объект 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>
Это не похоже на очень угловой способ сделать это. Я не совсем уверен, почему это не работает, но вам, вероятно, потребуется доступ к области действия, чтобы использовать такую функцию.
Мое предложение было бы создать фильтр. Это угловой путь.
myModule.filter('ceil', function() {
return function(input) {
return Math.ceil(input);
};
});
Затем в вашем HTML сделайте это:
<p>The percentage is {{ (100*count/total) | ceil }}%</p>
number
Фильтр форматирует число с тысячами разделителей, так что это не строго математическая функция.
Более того, его десятичный «ограничитель» не содержит ceil
дробные десятичные дроби (как некоторые другие ответы заставят вас поверить), а скорее использует round
их.
Таким образом, для любой математической функции, которую вы хотите, вы можете внедрить ее (проще имитировать, чем внедрить весь объект Math) следующим образом:
myModule.filter('ceil', function () {
return Math.ceil;
});
Не нужно также оборачивать его в другую функцию.
Это более или менее краткое изложение трех ответов (Сара Инес Кальдерон, Клаксон и Готбурс), но, поскольку все они добавили что-то важное, я считаю, что стоит объединить решения и добавить еще несколько объяснений.
Рассматривая ваш пример, вы можете выполнять вычисления в своем шаблоне, используя:
{{ 100 * (count/total) }}
Однако это может привести к большому количеству десятичных разрядов, поэтому использование фильтров - хороший способ:
{{ 100 * (count/total) | number }}
По умолчанию числовой фильтр будет содержать до трех дробных цифр , здесь аргумент fraSize довольно удобно ( {{ 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>
подробнее об этом ниже.