AngularJS 바인딩의 수학 함수


232

AngularJS 바인딩에서 수학 함수를 사용하는 방법이 있습니까?

예 :

<p>The percentage is {{Math.round(100*count/total)}}%</p>

이 바이올린은 문제를 보여줍니다

http://jsfiddle.net/ricick/jtA99/1/


11
또 다른 옵션은 필터를 대신 사용하여 템플릿에서 Math를 사용하지 않는 것 <p>The percentage is {{(100*count/total)| number:0}}%</p>입니다.
앤드류 Kuklewicz

2
Angular2의 경우 컴포넌트 멤버를 정의 private Math = Math;하면 사용할 수 있습니다.
Ondra Žižka

답변:


329

수학에 대해 전혀 모르는 Math상태로 사용해야 할 경우 스코프 에 주입 해야합니다 $scope.

가장 간단한 방법은 할 수 있습니다

$scope.Math = window.Math;

컨트롤러에서. 이 작업을 올바르게 수행하는 방법은 수학 서비스를 만드는 것입니다.


1
감사. 완전히 다른 논리를 가진 여러 템플릿이 있고 가능한 한 많이 분리하려는 유스 케이스가 있습니다. 완벽
Yablargo

48
범위에 Math 개체를 배치하지 말고 필터를 사용해야합니다.
Soviut

4
이것은 빠르고 더러운 것들에 좋습니다. 빠르게 무언가를 조롱하거나 무언가가 어떻게 작동하는지 알고 싶어합니다. 아마도 html 템플릿 파일에서 수학하기를 원하는 사람이 원하는 것 같습니다.
Lan

1
바인딩에 함수를 사용하면 함수가 각 범위의 업데이트에서 호출하고 너무 많은 리소스를 사용하게됩니다.
desmati

이 솔루션은 잘못되었습니다 . 왜? 1- 글로벌 범위를 오염시키는 것은 최악의 생각입니다. 2- 뷰는를 담당 formatting하므로 대신 필터를 사용하십시오.
Afshin Mehrabani

304

Math이 특정 문제에 대해 각도로 사용하도록 주입 할 수있는 대답은 옳지 만 더 일반적인 / 각도 방법은 숫자 필터입니다.

<p>The percentage is {{(100*count/total)| number:0}}%</p>

number필터 에 대한 자세한 내용은 여기를 참조 하십시오. http://docs.angularjs.org/api/ng/filter/number


7
이것은 Angular 방식 일뿐만 아니라 올바른 방식입니다. 가치를 '포맷'하는 것은보기의 책임입니다.
Luke

39
앤드류,이 의견으로 게시물을 어수선하게해서 죄송합니다. 당신의 대답은 좋고 도움이됩니다. 그러나 다른 의견에 동의하지 않습니다. 나는 사람들이 마치“완전한 발전의 모범”인 것처럼“각도”를 선포 할 때 종종 울었다. 그렇지 않습니다. OP는 일반적으로 반올림과 함께 수학 함수를 바인딩에 포함시키는 방법을 질문했습니다. 이 답변은 순수 주의자들이 정확히 하나의 수학 문제를 해결하기위한 "각도"일지 모르지만, 그 질문에 완전히 대답하지는 않습니다.
kbrimington

1
고고학에 대해서는 유감이지만 출력으로 숫자가 필요할 때 올바르지 않습니다. 또는로 {{1234.567|number:2}}렌더링합니다 . 값을 전달하려고 하면 값이 올바른 숫자는 아니지만 로케일 종속 문자열 표현이므로 입력을 비 웁니다. 1,234.571 234,57<input type="number" ng-value="1234.567|number:2">
SWilk

61

가장 좋은 방법은 다음과 같이 필터를 만드는 것입니다.

myModule.filter('ceil', function() {
    return function(input) {
        return Math.ceil(input);
    };
});

마크 업은 다음과 같습니다.

<p>The percentage is {{ (100*count/total) | ceil }}%</p>

업데이트 된 바이올린 : http://jsfiddle.net/BB4T4/


klaxon의 답변에 제공된 숫자 필터는 이미 ceil을 수행하므로 필요하지 않습니다.
Kim

필자는 필터를 사용하여 타이머 자체를 원하는대로 만들었습니다. 즉, 현재 시간을 가져 와서 사용자 정의 필터를 사용하여 적합하다고 본 문자열로 형식화합니다. 또한 숫자 필터는 숫자를 반올림 할 때 유용하지만 바닥 및 천장 기능의 경우 쓸모가 없습니다.
Gabriel Lovetro

37

이것은 당신이하고있는 일에 대한 완전한 맥락을 제공하지 않았기 때문에 대답하기에 털이 많은 것입니다. 허용 된 답변은 작동하지만 경우에 따라 성능이 저하 될 수 있습니다. 그리고 테스트하기가 더 어려워 질 것입니다.

정적 양식의 일부로이 작업을 수행하는 경우 좋습니다. 수락하기 쉬운 답변은 테스트하기 쉽지 않더라도 잘 작동합니다.

이것에 대해 "Angular"가 되려면 :

뷰에서 "비즈니스 로직"(즉, 데이터가 표시되도록 변경하는 로직)을 유지해야합니다. 따라서 로직을 단위로 테스트 할 수 있으므로 컨트롤러와 뷰를 밀접하게 연결하지 않아도됩니다. 이론적으로 컨트롤러를 다른보기로 가리키고 범위에서 동일한 값을 사용할 수 있어야합니다. (그렇다면 말이됩니다).

또한 내부 바인딩 (예 : 모든 함수 호출 것을 고려할 것 {{}}또는 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.
  });
});

요소를 컴파일 한 다음 dom 요소에서 찾은 값을 테스트 할 수 있습니다. 현지화 필터를 사용하고 있기 때문에 실제로 선호됩니다.
FlavorScape

좋은 대답입니다. 그러나 왜 $window단지 계획으로 작동하는 것처럼 보이기 때문에 궁금해 Math.round()합니까?
Neel

3
@Neel-$ window를 사용하면 Math테스트 를보다 쉽게 ​​조롱 할 수 있습니다 . 대안 적으로 Math 서비스를 만들어서 주입 할 수 있습니다.
벤 레시

8

왜 전체 수학 객체를 필터로 감싸지 않겠습니까?

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'}}


8

더 나은 옵션은 다음을 사용하는 것입니다.

{{(100*score/questionCounter) || 0 | number:0}}

값이 초기화되지 않은 경우 방정식의 기본값을 0으로 설정합니다.



6

Angular를 사용하여 간단한 수학을 수행하는 가장 쉬운 방법은 페이지에서 대량 계산을 수행 할 필요가 없다고 가정 할 때 필요에 따라 개별 바인딩에 대한 HTML 마크 업에 직접있는 것입니다. 예를 들면 다음과 같습니다.

{{(data.input/data.input2)| number}} 

이 경우 ()에서 수학을 수행 한 다음 필터 | 숫자 답변을 얻을 수 있습니다. 각도 숫자를 텍스트로 형식화하는 방법에 대한 자세한 정보는 다음과 같습니다.

https://docs.angularjs.org/api/ng/filter


4

전역 Math 객체를 스코프에 바인딩합니다 (창이 아닌 $ 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>

2

그것은 그렇게하는 매우 Angular 방식처럼 보이지 않습니다. 왜 작동하지 않는지 완전히 알지 못하지만 그러한 기능을 사용하려면 범위에 액세스해야 할 것입니다.

내 제안은 필터를 만드는 것입니다. 이것이 각도 방식입니다.

myModule.filter('ceil', function() {
    return function(input) {
        return Math.ceil(input);
    };
});

그런 다음 HTML에서 다음을 수행하십시오.

<p>The percentage is {{ (100*count/total) | ceil }}%</p>

1

number은 엄격하게 수학이 작동하지 그래서 필터는 천 단위 구분와 수를 포맷합니다.

또한 십진수 'limiter'는 ceil잘린 소수 가 아니며 (다른 답변이 당신을 믿게 만들 수 있기 때문에) 오히려 숫자를 씁니다 round.

따라서 원하는 수학 함수에 대해 다음과 같이 주입 할 수 있습니다 (전체 Math 객체를 주입하는 것보다 조롱하는 것이 더 쉽습니다).

myModule.filter('ceil', function () {
  return Math.ceil;
});

다른 기능으로 감쌀 필요가 없습니다.


0

이것은 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 }}

이것은 또한 이미 결과를 반올림합니다 :

마지막으로, 외부 데이터 소스를 사용 하는 경우 적절한 대체 값제공 하는 것이 좋습니다 (그렇지 않으면 사이트에 NaN이 있거나 아무것도 표시되지 않을 수 있음).

{{ (100 * (count/total) | number:0) || 0 }}

참고 사항 : 사양에 따라 이미 낮은 수준 (예 :)에서 폴백 / 정의 폴백을 사용하여 더 정확할 수도 있습니다 {{(100 * (count || 10)/ (total || 100) | number:2)}}. 그러나 이것이 항상 의미가있는 것은 아닙니다 ..


0

파이프를 사용한 각도 타입 스크립트 예제.

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'}}

TypeError : Math [args]는 함수가 아닙니다
MattEnth
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.