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.