[angularjs] AngularJS 애플리케이션에 작은 유틸리티 기능을 어떻게 추가 할 수 있습니까?

AngularJS 응용 프로그램에 일부 유틸리티 기능을 추가하고 싶습니다. 예를 들면 다음과 같습니다.

$scope.isNotString = function (str) {
    return (typeof str !== "string");
}

서비스로 추가하는 가장 좋은 방법입니까? 내가 읽은 것에서이 작업을 수행 할 수 있지만 HTML 페이지에서이를 사용하고 싶습니다. 서비스에있는 경우 여전히 가능합니까? 예를 들어 다음을 사용할 수 있습니다.

 <button data-ng-click="doSomething()"
         data-ng-disabled="isNotString(abc)">Do Something
 </button>

누군가 내가 어떻게 이것을 추가 할 수 있는지 예를 들어 줄 수 있습니까? 서비스를 만들거나 다른 방법이 있습니까? 가장 중요한 것은 이러한 유틸리티 기능을 파일로 만들고 기본 설정의 다른 부분과 결합하지 않기를 원합니다.

몇 가지 해결책이 있지만 그중 어느 것도 명확하지 않다는 것을 알고 있습니다.

솔루션 1 -Urban에서 제안

$scope.doSomething = ServiceName.functionName;

여기서 문제는 20 개의 기능과 10 개의 컨트롤러가 있다는 것입니다. 내가 이것을했다면 각 컨트롤러에 많은 코드를 추가하는 것을 의미합니다.

해결책 2- 내가 제안

    var factory = {

        Setup: function ($scope) {

            $scope.isNotString = function (str) {
                return (typeof str !== "string");
            }

이것의 단점은 모든 컨트롤러가 시작될 때 $ scope를 통과 한 각 서비스에 대해 하나 이상의 이러한 설정 호출이 있다는 것입니다.

솔루션 3 -Urban에서 제안

일반 서비스를 작성하기 위해 도시에서 제안한 솔루션이 좋습니다. 내 주요 설정은 다음과 같습니다.

var app = angular
    .module('app', ['ngAnimate', 'ui.router', 'admin', 'home', 'questions', 'ngResource', 'LocalStorageModule'])
    .config(['$locationProvider', '$sceProvider', '$stateProvider',
        function ($locationProvider, $sceProvider, $stateProvider) {

            $sceProvider.enabled(false);
            $locationProvider.html5Mode(true);

이것에 일반 서비스를 추가해야합니까? 어떻게 할 수 있습니까?



답변

7/1/15 편집 :

나는 꽤 오래 전에이 답변을 썼고 한동안 각도를 많이 유지하지 않았지만이 답변이 여전히 상대적으로 인기가있는 것처럼 보이므로 @nicolas 아래는 좋습니다. 우선, $ rootScope를 주입하고 헬퍼를 연결하면 모든 컨트롤러에 추가 할 필요가 없습니다. 또한 추가하는 것이 Angular 서비스 또는 필터로 생각되어야하는 경우 그러한 방식으로 코드에 채택되어야한다는 데 동의합니다.

또한 현재 버전 1.4.2부터 Angular는 “Provider”API를 제공하며이 블록은 구성 블록에 주입 될 수 있습니다. 자세한 내용은 다음 자료를 참조하십시오.

https://docs.angularjs.org/guide/module#module-loading-dependencies

module.config 내부의 값에 대한 AngularJS 종속성 주입

요즘 Angular를 실제로 적극적으로 사용하지 않고 실제로 새로운 베스트를 준수한다는 것을 느끼지 않고 새로운 답변을 위험에 빠뜨리고 싶지 않기 때문에 아래의 실제 코드 블록을 업데이트 할 것이라고 생각하지 않습니다. 관행. 다른 사람이 그것에 대해 느끼면 반드시 그것을 찾으십시오.

2/3/14 편집 :

이것에 대해 생각하고 다른 답변을 읽은 후에 실제로 @Brent Washburne과 @Amogh Talpallikar가 가져온 방법의 변형을 선호한다고 생각합니다. 특히 isNotString () 또는 이와 유사한 유틸리티를 찾고 있다면. 여기서 명백한 장점 중 하나는 각도 코드 외부에서 다시 사용할 수 있으며 구성 기능 내에서 사용할 수 있다는 것입니다 (서비스로는 할 수 없음).

즉, 서비스를 올바르게 사용해야하는 일반적인 방법을 찾고 있다면 이전의 대답은 여전히 ​​좋은 방법이라고 생각합니다.

내가 지금 할 일은 :

app.js :

var MyNamespace = MyNamespace || {};

 MyNamespace.helpers = {
   isNotString: function(str) {
     return (typeof str !== "string");
   }
 };

 angular.module('app', ['app.controllers', 'app.services']).
   config(['$routeProvider', function($routeProvider) {
     // Routing stuff here...
   }]);

controller.js :

angular.module('app.controllers', []).
  controller('firstCtrl', ['$scope', function($scope) {
    $scope.helpers = MyNamespace.helpers;
  });

그런 다음 부분적으로 사용할 수 있습니다.

<button data-ng-click="console.log(helpers.isNotString('this is a string'))">Log String Test</button>

아래의 오래된 답변 :

서비스로 포함하는 것이 가장 좋습니다. 서비스로 포함하여 여러 컨트롤러에서 다시 사용하려는 경우 코드를 반복하지 않아도됩니다.

HTML 부분에서 서비스 기능을 사용하려면 해당 기능을 해당 컨트롤러의 범위에 추가해야합니다.

$scope.doSomething = ServiceName.functionName;

그런 다음 부분적으로 사용할 수 있습니다.

<button data-ng-click="doSomething()">Do Something</button>

이 모든 것을 정리하고 너무 번거 로움없이 해줄 수있는 방법이 있습니다 :

컨트롤러, 서비스 및 라우팅 코드 / 구성을 controllers.js, services.js 및 app.js의 세 파일로 분리하십시오. 최상위 계층 모듈은 “app”이며 app.controllers 및 app.services를 종속성으로 사용합니다. 그런 다음 app.controllers 및 app.services를 자체 파일에서 모듈로 선언 할 수 있습니다. 이 조직 구조는 Angular Seed 에서 가져온 것입니다 .

app.js :

 angular.module('app', ['app.controllers', 'app.services']).
   config(['$routeProvider', function($routeProvider) {
     // Routing stuff here...
   }]);  

services.js :

 /* Generic Services */
 angular.module('app.services', [])
   .factory("genericServices", function() {
     return {
       doSomething: function() {
         //Do something here
       },
       doSomethingElse: function() {
         //Do something else here
       }
    });

controller.js :

angular.module('app.controllers', []).
  controller('firstCtrl', ['$scope', 'genericServices', function($scope, genericServices) {
    $scope.genericServices = genericServices;
  });

그런 다음 부분적으로 사용할 수 있습니다.

<button data-ng-click="genericServices.doSomething()">Do Something</button>
<button data-ng-click="genericServices.doSomethingElse()">Do Something Else</button>

이렇게하면 각 컨트롤러에 한 줄의 코드 만 추가하고 해당 범위에 액세스 할 수있는 모든 서비스 기능에 액세스 할 수 있습니다.


답변

이 오래된 실에 와서 강조하고 싶었습니다.

1 °) 유틸리티 기능은 module.run을 통해 루트 스코프에 추가해야합니다. 이 목적으로 특정 루트 레벨 컨트롤러를 설치할 필요는 없습니다.

angular.module('myApp').run(function($rootScope){
  $rootScope.isNotString = function(str) {
   return (typeof str !== "string");
  }
});

2 °) 코드를 별도의 모듈로 구성하는 경우 각도 서비스 또는 팩토리를 사용 하여 다음과 같이 실행 블록에 전달 된 함수에 삽입해야합니다.

angular.module('myApp').factory('myHelperMethods', function(){
  return {
    isNotString: function(str) {
      return (typeof str !== 'string');
    }
  }
});

angular.module('myApp').run(function($rootScope, myHelperMethods){
  $rootScope.helpers = myHelperMethods;
});

3 °) 내 이해는보기에서 대부분의 경우 표시하는 문자열에 일종의 서식을 적용하기 위해 이러한 도우미 기능이 필요하다는 것입니다. 이 마지막 경우에 필요한 것은 각도 필터 를 사용하는 것입니다

그리고 낮은 수준의 도우미 메서드를 각도 서비스 또는 팩토리로 구조화 한 경우 필터 생성자 내에 삽입하십시오.

angular.module('myApp').filter('myFilter', function(myHelperMethods){
  return function(aString){
    if (myHelperMethods.isNotString(aString)){
      return
    }
    else{
      // something else 
    }
  }
);

그리고 당신의 관점에서 :

{{ aString | myFilter }}   


답변

일부 유틸리티 메소드를 정의하고 템플리트에서 사용 가능하게하려면 올바르게 이해하고 있습니까?

모든 컨트롤러에 추가 할 필요는 없습니다. 모든 유틸리티 메소드에 대해 단일 컨트롤러를 정의하고 해당 컨트롤러를 <html> 또는 <body>에 연결하십시오 (ngController 지시문 사용). <html> (어딘가, 기간) 또는 <body> (<head> 이외의 위치) 아래에있는 다른 컨트롤러는 해당 $ scope를 상속받으며 해당 메서드에 액세스 할 수 있습니다.


답변

유틸리티 기능을 추가하는 가장 쉬운 방법은 전역 기능을 유지하는 것입니다.

function myUtilityFunction(x) { return "do something with "+x; }

그런 다음 컨트롤러에 유틸리티 함수를 추가하는 가장 간단한 방법은 다음과 같이에 함수를 할당하는 것입니다 $scope.

$scope.doSomething = myUtilityFunction;

그러면 다음과 같이 호출 할 수 있습니다.

{{ doSomething(x) }}

또는 이와 같이 :

ng-click="doSomething(x)"

편집하다:

원래의 질문은 유틸리티 기능을 추가하는 가장 좋은 방법은 서비스를 통하는 것입니다. 기능이 충분히 단순하다면 (아니오가 isNotString()제공 한 예 와 같이) 아니오라고 말합니다 .

서비스 작성의 이점은 테스트 목적으로 서비스를 다른 것으로 (주입을 통해) 대체하는 것입니다. 극단적으로, 모든 단일 유틸리티 기능을 컨트롤러에 주입해야합니까?

문서는 단순히 (같은 컨트롤러의 동작을 정의 말한다 $scope.double) : http://docs.angularjs.org/guide/controller


답변

여기에 내가 사용하는 간단하고 작고 이해하기 쉬운 방법이 있습니다.
먼저 js에 서비스를 추가하십시오.

app.factory('Helpers', [ function() {
      // Helper service body

        var o = {
        Helpers: []

        };

        // Dummy function with parameter being passed
        o.getFooBar = function(para) {

            var valueIneed = para + " " + "World!";

            return valueIneed;

          };

        // Other helper functions can be added here ...

        // And we return the helper object ...
        return o;

    }]);

그런 다음 컨트롤러에서 도우미 객체를 주입하고 다음과 같은 사용 가능한 기능을 사용하십시오.

app.controller('MainCtrl', [

'$scope',
'Helpers',

function($scope, Helpers){

    $scope.sayIt = Helpers.getFooBar("Hello");
    console.log($scope.sayIt);

}]);


답변

상수 서비스를 그대로 사용할 수도 있습니다. 상수 호출 외부에서 함수를 정의하면 재귀도 가능합니다.

function doSomething( a, b ) {
    return a + b;
};

angular.module('moduleName',[])
    // Define
    .constant('$doSomething', doSomething)
    // Usage
    .controller( 'SomeController', function( $doSomething ) {
        $scope.added = $doSomething( 100, 200 );
    })
;


답변

컨트롤러 상속을 사용하지 않는 이유는 ng-view 내의 컨트롤러에서 HeaderCtrl 범위에 정의 된 모든 메서드 / 속성에 액세스 할 수 있다는 것입니다. $ scope.servHelper는 모든 컨트롤러에서 액세스 할 수 있습니다.

    angular.module('fnetApp').controller('HeaderCtrl', function ($scope, MyHelperService) {
      $scope.servHelper = MyHelperService;
    });


<div ng-controller="HeaderCtrl">
  <div ng-view=""></div>
</div>