1. ホーム
  2. javascript

[解決済み] ディレクティブコントローラ内のメソッドを他のコントローラから呼び出す

2022-09-10 22:54:26

質問

独自のコントローラを持つディレクティブがあります。以下のコードを見てください。

var popdown = angular.module('xModules',[]);

popdown.directive('popdown', function () {
    var PopdownController = function ($scope) {
        this.scope = $scope;
    }

    PopdownController.prototype = {
        show:function (message, type) {
            this.scope.message = message;
            this.scope.type = type;
        },

        hide:function () {
            this.scope.message = '';
            this.scope.type = '';
        }
    }

    var linkFn = function (scope, lElement, attrs, controller) {

    };

    return {
        controller: PopdownController,
        link: linkFn,
        replace: true,
        templateUrl: './partials/modules/popdown.html'
    }

});

これは、エラー/通知/警告のための通知システムであることを意味します。私がやりたいことは、別のコントローラ(ディレクティブではない)から、関数 show をこのコントローラ上で呼び出すことです。そして、その際に、私のリンク関数が、いくつかのプロパティが変更されたことを検出し、いくつかのアニメーションを実行することも望んでいます。

以下は、私が求めていることを例証するためのコードです。

var app = angular.module('app', ['RestService']);

app.controller('IndexController', function($scope, RestService) {
    var result = RestService.query();

    if(result.error) {
        popdown.notify(error.message, 'error');
    }
});

ですから show を呼び出すと popdown ディレクティブコントローラで、リンク関数もトリガーされ、アニメーションが実行される必要があります。どうすればそれを実現できるでしょうか?

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

これは興味深い質問で、私はこのようなものをどのように実装するかについて考え始めました。

私が思いついたのは これ(フィドル) ;

基本的に、コントローラからディレクティブを呼び出そうとするのではなく、すべてのポップダウンロジックを格納するモジュールを作成しました。

var PopdownModule = angular.module('Popdown', []);

モジュールに2つの factory と、どこにでも注入できる API のための directive で実際のポップダウン要素の振る舞いを定義しています。

ファクトリーは単にいくつかの関数を定義しています successerror で、いくつかの変数を記録しています。

PopdownModule.factory('PopdownAPI', function() {
    return {
        status: null,
        message: null,
        success: function(msg) {
            this.status = 'success';
            this.message = msg;
        },
        error: function(msg) {
            this.status = 'error';
            this.message = msg;
        },
        clear: function() {
            this.status = null;
            this.message = null;
        }
    }
});

このディレクティブはAPIをコントローラにインジェクトし、APIの変更を監視します(便宜上、bootstrap cssを使用しています)。

PopdownModule.directive('popdown', function() {
    return {
        restrict: 'E',
        scope: {},
        replace: true,
        controller: function($scope, PopdownAPI) {
            $scope.show = false;
            $scope.api = PopdownAPI;

            $scope.$watch('api.status', toggledisplay)
            $scope.$watch('api.message', toggledisplay)

            $scope.hide = function() {
                $scope.show = false;
                $scope.api.clear();
            };

            function toggledisplay() {
                $scope.show = !!($scope.api.status && $scope.api.message);               
            }
        },
        template: '<div class="alert alert-{{api.status}}" ng-show="show">' +
                  '  <button type="button" class="close" ng-click="hide()">&times;</button>' +
                  '  {{api.message}}' +
                  '</div>'
    }
})

次に app モジュールに依存する Popdown :

var app = angular.module('app', ['Popdown']);

app.controller('main', function($scope, PopdownAPI) {
    $scope.success = function(msg) { PopdownAPI.success(msg); }
    $scope.error   = function(msg) { PopdownAPI.error(msg); }
});

そして、HTMLは次のようになります。

<html ng-app="app">
    <body ng-controller="main">
        <popdown></popdown>
        <a class="btn" ng-click="success('I am a success!')">Succeed</a>
        <a class="btn" ng-click="error('Alas, I am a failure!')">Fail</a>
    </body>
</html>

完全に理想的な方法かどうかはわかりませんが、グローバルな感じのポップダウンディレクティブとの通信を設定するには合理的な方法だと思われました。

もう一度、参考までに フィドル .