角度ですべてのコントローラーで機能を利用できるようにできますか?


191

宣言foo内のどこからでも呼び出せるようにするユーティリティ関数がある場合ng-app。モジュール設定でグローバルにアクセスできるようにする方法はありますか、それともすべてのコントローラーのスコープに追加する必要がありますか?


これについては100%確信が持てませんが、次のようにモジュールで定義することもできmodule.value('myFunc', function(a){return a;});ます。それから、名前をコントローラに挿入します。(サービスの作成を避けたい場合)
user2173353

つまり、すべてのコントローラーに手動で追加する必要があります。$ rootScopeは、ほぼ2年前に私がやりたかったことを実行する方法です=)
Ludwig Magnusson

OK。:)私はプレーンコントローラーよりも分離されたスコープを持つディレクティブを使用することが多く、とにかくすべてを注入する必要があります。これが提供するモジュラーコードスタイルが気に入っています。また、何らかの方法で親スコープを混乱させる必要はなく、スコープ変数の出所をあまり検索する必要もありません。:)
user2173353 2014年

回答:


290

基本的に2つのオプションがあります。サービスとして定義するか、ルートスコープに配置します。ルートスコープを汚染しないように、サービスを利用してサービスを作成することをお勧めします。次のようにして、サービスを作成し、コントローラーで利用できるようにします。

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
    var myApp = angular.module('myApp', []);

    myApp.factory('myService', function() {
        return {
            foo: function() {
                alert("I'm foo!");
            }
        };
    });

    myApp.controller('MainCtrl', ['$scope', 'myService', function($scope, myService) {
        $scope.callFoo = function() {
            myService.foo();
        }
    }]);
    </script>
</head>
<body ng-controller="MainCtrl">
    <button ng-click="callFoo()">Call foo</button>
</body>
</html>

それが選択肢にならない場合は、次のようにルートスコープに追加できます。

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
    var myApp = angular.module('myApp', []);

    myApp.run(function($rootScope) {
        $rootScope.globalFoo = function() {
            alert("I'm global foo!");
        };
    });

    myApp.controller('MainCtrl', ['$scope', function($scope){

    }]);
    </script>
</head>
<body ng-controller="MainCtrl">
    <button ng-click="globalFoo()">Call global foo</button>
</body>
</html>

これにより、globalFoo()コントローラーからテンプレートに渡す必要なく、すべてのテンプレートを呼び出すことができます。


5
最初の解決策では、大量のfoo()関数がある場合はどうなりますか?$scope.callFoo()それらすべてのラッパーを作るのは大変な作業です。ライブラリのすべての関数をスコープに「アタッチ」して、テンプレートで使用できるようにするにはどうすればよいですか?テンプレートで使用できるようにする大きな単位変換ライブラリがあります。
AlexStack 2014年

3
私の質問も。私はこれを試してみましたが、機能します$scope.callFoo = myService.foo;。使用したい場所ごとに新しいラッパーを作成する代わりに、「アタッチ」して言うことができます。
Fitter Man

1
あなたの助けをありがとう、私は自分のアプリ全体で言語変更機能を利用可能にする方法を考えていました、そして$ rootScopeが仕事をしました。他のアプリにもプラグインできるように、翻訳モジュールをアプリケーションとは別にしたかったです。
パウロ・ペドロソ

サービス内で複数の機能を使用する予定がない限り、この特定のケースではファクトリではなく角度値を使用することをお勧めします。関数が1つだけの場合は、値にします。
Nicholas Blasgen

エラーが発生しました:[$ injector:unpr]
Mark Thien

53

それらを組み合わせることもできます。

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
        var myApp = angular.module('myApp', []);

        myApp.factory('myService', function() {
            return {
                foo: function() {
                    alert("I'm foo!");
                }
            };
        });

        myApp.run(function($rootScope, myService) {
            $rootScope.appData = myService;
        });

        myApp.controller('MainCtrl', ['$scope', function($scope){

        }]);

    </script>
</head>
<body ng-controller="MainCtrl">
    <button ng-click="appData.foo()">Call foo</button>
</body>
</html>

7
これは@Praymの答えによって正当化される正しい答えになるはずだと思います。10の異なるコントローラーでサービスの依存関係を指定しても意味がありません。
jvannistelrooy 2014

サービスに、プロパティ/変数をCRUDできるメソッド/関数を含めることができ$rootScopeますか?
jezmck 2015

44

最初のアプローチは「角度のような」アプローチとして提唱されていますが、これによりオーバーヘッドが増えると感じています。

このmyservice.foo関数を10の異なるコントローラーで使用するかどうかを検討します。この 'my​​Service'依存関係を指定してから、10個すべてで$ scope.callFooスコーププロパティを指定する必要があります。これは単なる繰り返しであり、何らかの形でDRYの原則に違反しています。

一方、$ rootScopeアプローチを使用する場合は、このグローバル関数gobalFooを1回だけ指定すれば、将来のすべてのコントローラーで使用できます。


5
コントローラがそのグローバルサービスコールを取得する「ドキュメント化」に何らかの価値がある場合があります。コントローラーの1つを別のアプリケーションにヤンクすると、そのグローバル関数がどこから来たのかがはっきりしなくなります。私はあなたの議論を認めると聞きます。
マシューペイン

ビューから呼び出す必要がある場合にのみ、スコープに配置する必要があります。コントローラーでは、サービスから直接呼び出すことができます。
mcv 2015年

10
これは回答ではなくコメントです
エリオット

$ rootScope変数は、ページの更新時に常にnullになります。その場合、関数は取得されません。そのため、サービスを注入し、アプリケーションでその参照を使用するのが良いでしょう。
Ehsan Hafeez 2017

4

AngularJsには、「サービス」と「ファクトリー」があります。これらは、コントローラー、ディレクティブ、その他のサービス、またはその他のangularjsコンポーネント間でグローバルなものを使用するために使用されます。関数の定義、データの保存、関数の計算などを行うことができます。内側にしたいサービスとしてAngularJsコンポーネントにそれらを使用するグローバル .like

angular.module('MyModule', [...])
  .service('MyService', ['$http', function($http){
    return {
       users: [...],
       getUserFriends: function(userId){
          return $http({
            method: 'GET',
            url: '/api/user/friends/' + userId
          });
       }
       ....
    }
  }])

もっと必要なら

AngularJsサービスとファクトリが必要な理由の詳細


0

私はAngularの方が少し新しいですが、実行するのに便利(そして非常に単純)なのは、とにかくすべてのページでアクセスする必要があるグローバル変数を使用したローカルスクリプトの前に、ページにロードするグローバルスクリプトを作成したことです。このスクリプトでは、「globalFunctions」というオブジェクトを作成し、プロパティとしてグローバルにアクセスする必要がある関数を追加しました。例えばglobalFunctions.foo = myFunc();。次に、各ローカルスクリプトで$scope.globalFunctions = globalFunctions;記述し、グローバルスクリプトのglobalFunctionsオブジェクトに追加した関数にすぐにアクセスできます。

これは少しの回避策であり、あなたに役立つとは思えませんが、私には多くの機能があり、すべての機能を各ページに追加するのが面倒だったので、確実に役立ちました。


1
なぜ反対票に興味があるのですか?私は新しいので、プロから知りたいです。
Izzy、

私にとっては有効な解決策のようです。スコープが十分に分離されていることを確認するために私が提唱する唯一のことは、グローバルルートJavascriptユーティリティクラスを作成し、そこからユーティリティメソッドをハングアップさせることです。これにより、 Angularによって注入された広大な海。
JEカーターII

注意すべきこと、そしておそらくこれが反対されている理由の1つは、これらの関数はテンプレートでのみ使用でき、.tsモジュールではなく、関数呼び出しがコンパイル時に解決されないためです。これが「角度のある」方法で行う理由です。ただし、テンプレートにデコレータなどを追加したいだけの場合、グローバルユーティリティファイルはシンプルで問題ありません。
JEカーターII
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.