34

ディレクティブからメソッドを公開するにはどうすればよいですか? データに属性を使用する必要があることはわかっていますが、実際にはdataではなくbehaviorを公開したいと考えています。親コントローラーが呼び出すことができるもの。

私のDOMが次のようになっているとしましょう:

<div ng-app="main">
    <div ng-controller="MyCtrl">
        <button ng-click="call()" >Call</button>
        <div id="container" my-directive> </div>
    </div>
</div>

JavaScript:

angular.module("main", []).controller("MyCtrl", function($scope) {
    $scope.call = function() {
        $scope.myfn();
    };
}).directive("myDirective", function() {
    return {
        // scope: {},
        controller: function($scope) {
            $scope.myfn = function() {
                console.log("myfn called");
            }
        }
    };
});

jsFiddle: http://jsfiddle.net/5gDjQ/7/

scopeがコメントアウトされている場合(つまり、ディレクティブに独立したスコープがない場合)、問題なく動作します。ボタンを押すと、myfnが呼び出され、コンソールにログが記録されます。

コメントを外すとすぐにscope、機能しません。myfn子スコープで定義されており、親が簡単に利用できません。

私の場合、親スコープを汚染することは悪い考えであり、本当に避けたいと思います。

では、ディレクティブから親コントローラーに関数を公開するにはどうすればよいでしょうか? または: 親コントローラーからディレクティブでメソッドを呼び出すにはどうすればよいですか?

4

5 に答える 5

26

これは、コントローラーに双方向でバインドされたスコープ内の変数を設定することにより ('=' を使用)、分離されたスコープで行うことができます。ディレクティブでその変数に関数を割り当てると、angular はバインディングを使用してコントローラー内の対応する変数を見つけます。その変数は、コントローラーが呼び出すことができる関数を指します。

http://jsfiddle.net/GWCCr/

html: 新しい属性に注意してください:

<div ng-app="main">
    <div ng-controller="MyCtrl">
        <button ng-click="call()" >Call</button>
        <div id="container" my-directive my-fn="fnInCtrl"> </div>
    </div>
</div>

js:

angular.module("main", []).controller("MyCtrl", function($scope) {
    $scope.call = function() {
        $scope.fnInCtrl();
    };
}).directive("myDirective", function() {
    return {
        scope: {
            myFn: '='
        },
        controller: function($scope) {
            $scope.myFn = function() {
                console.log("myfn called");
            }
        }
    };
});
于 2013-04-10T20:07:43.147 に答える
17

ディレクティブ内に隠されている関数を呼び出す方法を理解しようとするのではなく、自問すべきだと思います:なぜディレクティブで定義された関数を呼び出す必要があるのか​​?

私が考えることができる理由の 1 つは、ディレクティブ内からアプリケーションのユーザーによってトリガーされる可能性のあるディレクティブの動作をトリガーすることです

もしそうなら、明白でAngularのやるべきことは、それに反応すべきディレクティブを含むスコープでイベントをブロードキャストすることです。次に、ディレクティブはそのイベントをリッスンし、それ自体でその機能をトリガーします。

これには追加の利点があります。

  • 必要に応じて、イベント データ オブジェクトでパラメーターを送信できます。
  • 複数のディレクティブで反応をトリガーできます (例: それらがコレクションを形成する場合)
  • ネストされたディレクティブごとに関数コールバックを渡すことなく、スコープ階層の深いディレクティブと通信できます (たとえば、ディレクティブが他のディレクティブ内にある別のディレクティブ内にある場合など)。
  • ディレクティブの分離を壊しません

非常に単純な例を考えてみましょう。どこかからダウンロードしたランダムな心に強く訴える引用を表示するウィジェットがあるとします。また、引用を別のものに変更するためのボタンもあります。

ディレクティブのテンプレートは次のとおりです。

<p>{{ quote }}</p>
<button ng-click="refreshQuote()"></button>

ディレクティブのコードは次のとおりです。

app.directive("randomQuote", function () {
  return {
    restrict: "E",
    scope: {},
    link: function (scope) {
      scope.refreshQuote = function () {
        scope.quote = ... // some complicated code here
      };
      scope.refreshQuote();
    }
  };
});

このディレクティブは完全に自己完結型であることに注意してください。これには、isolate スコープがあり、それ自体で引用フェッチを行います。

コントローラーからの引用も更新できるようにしたいとしましょう。これは、コントローラーコードでこれを呼び出すのと同じくらい簡単です。

$scope.$broadcast("refresh-random-quote");

イベント ハンドラーを追加するには、次のコードをlinkディレクティブの関数に追加する必要があります。

scope.$on("refresh-random-quote", function () {
  scope.refreshQuote();
});

このようにして、コントローラーからディレクティブへの一方向の通信チャネルを作成しました。これは、ディレクティブの分離を壊さず、イベントをブロードキャストするコードのスコープ階層にディレクティブが深くネストされている場合にも機能します。 .

于 2015-09-19T07:59:31.827 に答える
7

ディレクティブから親コントローラーに関数を公開するにはどうすればよいですか?
または: 親コントローラーからディレクティブでメソッドを呼び出すにはどうすればよいですか?

ええと、これをやろうとするべきではないと思います (つまり、コントローラーの動作をディレクティブに結合する) 必要がある場合は... 1 つの方法があります: コントローラー関数をディレクティブに渡します。ディレクティブは、コントローラーにディレクティブ関数を通知するために呼び出すことができます。

<div id="container" my-directive cb="setDirectiveFn(fn)"></div>

directive("myDirective", function() {
    return {
       scope: { cb: '&' },
        controller: function($scope) {
            $scope.myfn = function() {
                console.log("myfn called");
            }
            $scope.cb({fn: $scope.myfn});
        }
    };
});

フィドル

于 2013-04-10T20:08:44.983 に答える
2

AngularJS V1.7.1 *のリリースでは、新しいng-ref ディレクティブが導入されています。

ng-ref属性は、現在のスコープでコンポーネントのコントローラーを公開するように AngularJS に指示します。これは、オーディオ プレーヤーなどのコンポーネントがその API を兄弟コンポーネントに公開する場合に便利です。再生と停止のコントロールに簡単にアクセスできます。

詳細については、次を参照してください。

于 2018-12-11T22:15:34.790 に答える