AngularJS-関数をディレクティブに渡す


160

angularJSの例があります

<div ng-controller="testCtrl">

<test color1="color1" updateFn="updateFn()"></test>
</div>
 <script>
  angular.module('dr', [])
.controller("testCtrl", function($scope) {
    $scope.color1 = "color";
    $scope.updateFn = function() {
        alert('123');
    }
})
.directive('test', function() {
    return {
        restrict: 'E',
        scope: {color1: '=',
                updateFn: '&'},
        template: "<button ng-click='updateFn()'>Click</button>",
        replace: true,
        link: function(scope, elm, attrs) { 
        }
    }
});

</script>
</body>

</html>

ボタンをクリックすると、警告ボックスが表示されますが、何も表示されません。

誰か助けてもらえますか?

回答:


243

Isolate Scopeディレクティブ内から親スコープのコントローラー関数を呼び出すにはdash-separated、OPで述べたようにHTMLで属性名を使用します。

また、関数にパラメーターを送信する場合は、オブジェクトを渡して関数を呼び出します。

<test color1="color1" update-fn="updateFn(msg)"></test>

JS

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

app.controller("testCtrl", function($scope) {
    $scope.color1 = "color";
    $scope.updateFn = function(msg) {        
        alert(msg);
    }
});

app.directive('test', function() {
    return {
        restrict: 'E',
        scope: {
            color1: '=',
            updateFn: '&'
        },
        // object is passed while making the call
        template: "<button ng-click='updateFn({msg : \"Hello World!\"})'>
            Click</button>",
        replace: true,        
        link: function(scope, elm, attrs) {             
        }
    }
});

Fiddle


1
Codezillaの回答に感謝します。ディレクティブ "test"でスコープを分離するために親スコープから関数 "updateFn"をバインドする状況について質問します。それは可能ですか?
user2707026 2013

2
replace属性はAngularJSで廃止されました:stackoverflow.com/questions/24194972/...
cdmckay

8
なんらかの理由で、引数は私には定義されていません。
2015年

1
@chovy引数はメソッドをもう一度呼び出したときにのみ使用されると思いますか?最初の開き角括弧の使用法は、angularがメソッドを渡したいだけの形式のようですが、私はそこで間違っているかもしれません
markyzm

1
updateFn({msg: 'my message'});ディレクティブのlink関数内で関数呼び出しを行うときは、オブジェクトマッピングをその形式で使用する必要があります。
ブライアン

159

おそらく何か不足しているかもしれませんが、他のソリューションは親スコープ関数を呼び出しますが、ディレクティブコードから引数を渡すことができません。これは、などのupdate-fnupdateFn()固定パラメータで呼び出しているためです{msg: "Hello World"}。わずかな変更により、ディレクティブが引数を渡すことができるようになりました。

<test color1="color1" update-fn="updateFn"></test>

HTMLが関数参照を渡していることに注意してください()

JS

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

app.controller("testCtrl", function($scope) {
    $scope.color1 = "color";
    $scope.updateFn = function(msg) {        
        alert(msg);
    }
});

app.directive('test', function() {
    return {
        restrict: 'E',
        scope: {
            color1: '=',
            updateFn: '&'
        },
        // object is passed while making the call
        template: "<button ng-click='callUpdate()'>
            Click</button>",
        replace: true,        
        link: function(scope, elm, attrs) {       
          scope.callUpdate = function() {
            scope.updateFn()("Directive Args");
          }
        }
    }
});

したがって、上記では、HTMLがローカルスコープcallUpdate関数を呼び出しています。これにより、親スコープからupdateFnが「フェッチ」され、ディレクティブが生成できるパラメーターを使用して返された関数が呼び出されます。

http://jsfiddle.net/mygknek2/


9
うまくいくものに私がどのようにして反対票を投じることができるかわかりませんか?反対票を投じる場合はコメントを残してください。
2015

7
これでうまくいきました。追加の機能が必要ない場合は、次のように入力してくださいng-click="updateFn()('Directive Args')"
Graham Walters

7
わぁぁぁぁぁぁぁぁぁ!scope.updateFn()( "Directive Args"); !! NOT scope.updateFn( "Directive Args"); !!!
Phung D. An、2015

2
これは確かにもっと完璧な答えです!
vinesh

11
@ Ludwik11確かに-これは、このように定義された場合のscope.updateFnが関数(つまり()())を返す関数であり、これがスコープに(htmlのupdate-fn = "updateFn"を介して)参照を渡すためです呼び出したい関数に。1番目の()はこの参照を返すためのangularの呼び出しで、2番目の()は関数への呼び出しを行い、パラメーターを渡す場所です。HTH
2016

39

'test'ディレクティブのHtmlタグでは、関数の属性名はcamelCasedではなく、ダッシュベースにする必要があります。

そう-の代わりに:

<test color1="color1" updateFn="updateFn()"></test>

書く:

<test color1="color1" update-fn="updateFn()"></test>

これは、ディレクティブ属性(update-fn関数など)と関数の違いを区別するためのAngularの方法です。


1
キャッチをありがとう。私はそれを私の答えに含めました。投票しました!:)
AlwaysALearner 2014年

10

双方向バインディングでコントローラー関数を渡すのはどうですか?次に、通常のテンプレートとまったく同じ方法でディレクティブで使用できます(単純にするために、関係のない部分を削除しました)。

<div ng-controller="testCtrl">

   <!-- pass the function with no arguments -->
   <test color1="color1" update-fn="updateFn"></test>
</div>

<script>
   angular.module('dr', [])
   .controller("testCtrl", function($scope) {
      $scope.updateFn = function(msg) {
         alert(msg);
      }
   })
   .directive('test', function() {
      return {
         scope: {
            updateFn: '=' // '=' bidirectional binding
         },
         template: "<button ng-click='updateFn(1337)'>Click</button>"
      }
   });
</script>

上記の方法を試してみたので、この質問にたどり着きましたが、どういうわけかうまくいきませんでした。今では完全に動作します。


5

属性名にはダッシュと小文字を使用します(他の答えが言ったように):

 <test color1="color1" update-fn="updateFn()"></test>

ディレクティブスコープで「&」の代わりに「=」を使用します。

 scope: { updateFn: '='}

その後、他の関数と同様にupdateFnを使用できます。

 <button ng-click='updateFn()'>Click</button>

よし!


5
なぜ「&」の代わりに「=」を使用するのですか?私がこれを試したとき、それは私の関数を繰り返し呼び出し続けました。
user1012500 2016年

2
これに「=」を使用するのは間違っています。これは、双方向のオブジェクトバインディング用です。
Ben Taliadoros 2017年

1
唯一の問題は、最初のテンプレートでの括弧の使用です。これにより関数が実行され、結果がバインドされます。代わりに、次のように関数の名前のみを渡す必要があります。update-fn="updateFn"
MártonTamás17年

1
悪い答え。ひどい。
17

4

「&」の代わりに「=」バインディングを使用する必要がありました。奇妙な行動。


2
これは、ディレクティブに実行ではなくJS関数参照を渡す可能性が高いためです。関数を引数としてディレクティブに渡すときupdate-fn="updateFn()"は、括弧(およびおそらくparams)を含める必要があります。関数参照として渡してもupdate-fn="updateFn"&バインディングでは機能しません
JorgeGRC

0

@JorgeGRCご回答ありがとうございます。ただし、「たぶん」の部分は非常に重要です。パラメータがある場合は、それもテンプレートに含めて、必ずローカルなどを指定する必要がありますupdateFn({msg: "Directive Args"}

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.