1. ホーム
  2. angularjs

[解決済み] AngularJSアプリケーションに小さなユーティリティ関数を追加するには?

2022-05-09 14:31:41

質問

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を渡す各サービスへのSetupコールが1つ以上あることです。

解決策3 - 提案者:Urban

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);

これにジェネリックサービスを追加する必要がありますか?

どのように解決するのですか?

EDIT 7/1/15:

この回答を書いたのはかなり前のことで、しばらくはangularをあまり追いかけていませんでしたが、この回答はまだ比較的人気があるようなので、以下の@nicolasの指摘がいくつか良いことを指摘したいと思います。1つは、$rootScopeを注入し、そこにヘルパーをアタッチすることで、すべてのコントローラでヘルパーを追加する必要がなくなります。また、追加するものがAngularサービスまたはフィルタとみなされるのであれば、そのようにコードに採用されるべきであるということに同意します。

また、現在のバージョン1.4.2では、Angularは"Provider"APIを公開しており、configブロックへの注入が許可されています。詳しくはこちらのリソースをご覧ください。

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

モジュール.config内の値のAngularJS依存性注入

なぜなら、私は最近Angularをあまり積極的に使っておらず、新しいベストプラクティスに適合しているという安心感なしに、新しい答えを危険にさらすことはしたくないからです。もし他の人がそう思うなら、ぜひやってください。

2/3/14の編集。

このことについて考え、他のいくつかの回答を読んだ後、私は実際に@Brent Washburneと@Amogh Talpallikarによってもたらされた方法のバリエーションが好きだと思います。特に、isNotString() などのユーティリティを探しているのならなおさらです。ここでの明確な利点の1つは、angularコードの外側でそれらを再利用できることと、config関数の内側でそれらを使用できることです(これはserviceではできないことです)。

とはいえ、本来サービスであるべきものを再利用する汎用的な方法を探しているのであれば、私が考える古い答えは今でも良いものだと思います。

今ならどうするかというと

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の3つのファイルに分けてください。最上層のモジュールは、"app" で、app.controllers と app.services を依存関係として持っています。そして、app.controllersとapp.servicesは、それぞれ独自のファイルでモジュールとして宣言することができます。この組織構造は、ちょうど アンギュラーシード :

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行のコードを追加するだけで、そのスコープがアクセス可能な場所であれば、どのサービス関数にもアクセスできるようになります。