2013-04-13 17 views
66

私の前のquestionに続いて、私は親ディレクターのメソッドを私のディレクティブから呼び出そうとしています。私は未定義のパラメータを取得します。ここでは、私が何をすべきかです:AngularJSのディレクティブからの親コントローラの呼び出しメソッド

<body ng-app="myApp" ng-controller="MainCtrl"> 
    <span>{{mandat.rum}}</span> 
    <span>{{mandat.surname}}</span> 
<input type="text" ng-model="mandat.person.firstname" /> 
<my-directive mandate-person="mandat.person" updateparent="updatePerson()" > 

    </my-directive> 
</body> 

とスクリプト:updatePersonメソッドが呼び出されたときに

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

    app.controller('MainCtrl', function ($scope) { 
     $scope.mandat = { name: "John", surname: "Doe", person: { id: 1408, firstname: "sam" } }; 
     $scope.updatePerson = function(person) { 
      alert(person.firstname); 
      $scope.mandat.person = person; 
     } 
    }); 


    app.directive('myDirective', function() { 
     return { 
      restrict: 'E', 
      template: "<div><span>{{mandatePerson.id}}<span><input type='text' ng-model='mandatePerson.firstname' /><button ng-click='updateparent({person: mandatePerson})'>click</button></div>", 
      replace: true, 
      scope: { mandatePerson: '=', updateparent: '&' } 
      } 
     } 
    ) 

、人は未定義です。ここ

jsfiddle:http://jsfiddle.net/graphicsxp/Z5MBf/7/

答えて

54

だけで簡単な変更

<my-directive mandate-person="mandat.person" updateparent="updatePerson(person)" > 

     </my-directive> 

の下にあなたがupdatePersonと "人" を渡していないとして、あなたのhtmlなぜそれが機能していないthatsの

+0

ので、私はやっている右、親スコープを更新するための正しい方法は何ですか?私は "人"を渡すことを忘れてしまった。 – Sam

+0

右端 –

+4

最初に混乱していた人には、テンプレート内のng-clickでオブジェクト表記を気にしてください: 'ng-click = 'updateparent({person:mandatePerson})' ' – ErikAGriffin

12

は2つの方法があり、 &=を使用して呼び出すことができます。

私は

ng-click='updateparent({person: mandatePerson})' 

ng-click='updateparent(mandatePerson)' 

し、ディレクティブに変更されます、その後、scope属性ため=を使用していた場合は、

updateparent="updatePerson()" 

updateparent="updatePerson" 

にここに引数を言及する必要性を全く変えないだろう、彼らは参考にコントローラの関数定義に渡されます。

&を使用することは他の回答で説明されています。

+1

ありがとうございます。コントローラのメソッド '='を使用すると、ディレクティブインスタンスのすべての引数を宣言する必要がないため、 '&'を使用するほうが簡単です –

+1

午後、ディレクティブを修正しようとしました。問題は、ディレクティブ宣言の引数です(渡された引数が存在しないために定義されていたためです)。 ありがとうございました! –

37

コントローラメソッドへのアクセスとは、指示子controller/link/scopeから親スコープのメソッドにアクセスすることを意味します。

ディレクティブが親スコープを共有/継承している場合は、親スコープメソッドを呼び出すだけでかなり簡単です。

隔離された指示スコープから親スコープのメソッドにアクセスするには、少しだけ作業が必要です。

分離ディレクティブスコープまたはウォッチ親スコープ変数(オプション#6)から親スコープメソッドを呼び出すためのオプションはいくつかあります。

これらの例ではlink functionを使用しましたが、要件に応じてdirective controllerを使用することもできます。

オプション#1。リテラルとディレクティブのHTMLテンプレートからオブジェクトを介して

index.html

<!DOCTYPE html> 
<html ng-app="plunker"> 

    <head> 
    <meta charset="utf-8" /> 
    <title>AngularJS Plunker</title> 
    <script>document.write('<base href="' + document.location + '" />');</script> 
    <link rel="stylesheet" href="style.css" /> 
    <script data-require="[email protected]" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script> 
    <script src="app.js"></script> 
    </head> 

    <body ng-controller="MainCtrl"> 
    <p>Hello {{name}}!</p> 

    <p> Directive Content</p> 
    <sd-items-filter selected-items="selectedItems" selected-items-changed="selectedItemsChanged(selectedItems)" items="items"> </sd-items-filter> 


    <P style="color:red">Selected Items (in parent controller) set to: {{selectedItemsReturnedFromDirective}} </p> 

    </body> 

</html> 

itemfilterTemplate.html

<select ng-model="selectedItems" multiple="multiple" style="height: 200px; width: 250px;" ng-change="selectedItemsChanged({selectedItems:selectedItems})" ng-options="item.id as item.name group by item.model for item in items | orderBy:'name'"> 
    <option>--</option> 
</select> 

app.js

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

app.directive('sdItemsFilter', function() { 
    return { 
    restrict: 'E', 
    scope: { 
     items: '=', 
     selectedItems: '=', 
     selectedItemsChanged: '&' 
    }, 
    templateUrl: "itemfilterTemplate.html" 
    } 
}) 

app.controller('MainCtrl', function($scope) { 
    $scope.name = 'TARS'; 

    $scope.selectedItems = ["allItems"]; 

    $scope.selectedItemsChanged = function(selectedItems1) { 
    $scope.selectedItemsReturnedFromDirective = selectedItems1; 
    } 

    $scope.items = [{ 
    "id": "allItems", 
    "name": "All Items", 
    "order": 0 
    }, { 
    "id": "CaseItem", 
    "name": "Case Item", 
    "model": "PredefinedModel" 
    }, { 
    "id": "Application", 
    "name": "Application", 
    "model": "Bank" 
    }] 

}); 

作業plnkr:http://plnkr.co/edit/rgKUsYGDo9O3tewL6xgr?p=preview

オプション#2。オブジェクトリテラルとディレクティブのリンクから/スコープ

index.html

<!DOCTYPE html> 
<html ng-app="plunker"> 

    <head> 
    <meta charset="utf-8" /> 
    <title>AngularJS Plunker</title> 
    <script>document.write('<base href="' + document.location + '" />');</script> 
    <link rel="stylesheet" href="style.css" /> 
    <script data-require="[email protected]" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script> 
    <script src="app.js"></script> 
    </head> 

    <body ng-controller="MainCtrl"> 
    <p>Hello {{name}}!</p> 

    <p> Directive Content</p> 
    <sd-items-filter selected-items="selectedItems" selected-items-changed="selectedItemsChanged(selectedItems)" items="items"> </sd-items-filter> 


    <P style="color:red">Selected Items (in parent controller) set to: {{selectedItemsReturnedFromDirective}} </p> 

    </body> 

</html> 

itemfilterTemplate.html

<select ng-model="selectedItems" multiple="multiple" style="height: 200px; width: 250px;" 
ng-change="selectedItemsChangedDir()" ng-options="item.id as item.name group by item.model for item in items | orderBy:'name'"> 
    <option>--</option> 
</select> 

app.js

を通じて、

作業plnkr:http://plnkr.co/edit/BRvYm2SpSpBK9uxNIcTa?p=preview

オプション#3。関数の参照を通って、ディレクティブのHTMLテンプレートから

index.html

<!DOCTYPE html> 
<html ng-app="plunker"> 

    <head> 
    <meta charset="utf-8" /> 
    <title>AngularJS Plunker</title> 
    <script>document.write('<base href="' + document.location + '" />');</script> 
    <link rel="stylesheet" href="style.css" /> 
    <script data-require="[email protected]" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script> 
    <script src="app.js"></script> 
    </head> 

    <body ng-controller="MainCtrl"> 
    <p>Hello {{name}}!</p> 

    <p> Directive Content</p> 
    <sd-items-filter selected-items="selectedItems" selected-items-changed="selectedItemsChanged" items="items"> </sd-items-filter> 


    <P style="color:red">Selected Items (in parent controller) set to: {{selectedItemsReturnFromDirective}} </p> 

    </body> 

</html> 

itemfilterTemplate.html

<select ng-model="selectedItems" multiple="multiple" style="height: 200px; width: 250px;" 
ng-change="selectedItemsChanged()(selectedItems)" ng-options="item.id as item.name group by item.model for item in items | orderBy:'name'"> 
    <option>--</option> 
</select> 

app.js

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

app.directive('sdItemsFilter', function() { 
    return { 
    restrict: 'E', 
    scope: { 
     items: '=', 
     selectedItems:'=', 
     selectedItemsChanged: '&' 
    }, 
    templateUrl: "itemfilterTemplate.html" 
    } 
}) 

app.controller('MainCtrl', function($scope) { 
    $scope.name = 'TARS'; 

    $scope.selectedItems = ["allItems"]; 

    $scope.selectedItemsChanged = function(selectedItems1) { 
    $scope.selectedItemsReturnFromDirective = selectedItems1; 
    } 

    $scope.items = [{ 
    "id": "allItems", 
    "name": "All Items", 
    "order": 0 
    }, { 
    "id": "CaseItem", 
    "name": "Case Item", 
    "model": "PredefinedModel" 
    }, { 
    "id": "Application", 
    "name": "Application", 
    "model": "Bank" 
    }] 
}); 

作業plnkr:http://plnkr.co/edit/Jo6FcYfVXCCg3vH42BIz?p=preview

オプション#4。関数参照を通って指令リンク/範囲から

index.html

<!DOCTYPE html> 
<html ng-app="plunker"> 

    <head> 
    <meta charset="utf-8" /> 
    <title>AngularJS Plunker</title> 
    <script>document.write('<base href="' + document.location + '" />');</script> 
    <link rel="stylesheet" href="style.css" /> 
    <script data-require="[email protected]" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script> 
    <script src="app.js"></script> 
    </head> 

    <body ng-controller="MainCtrl"> 
    <p>Hello {{name}}!</p> 

    <p> Directive Content</p> 
    <sd-items-filter selected-items="selectedItems" selected-items-changed="selectedItemsChanged" items="items"> </sd-items-filter> 


    <P style="color:red">Selected Items (in parent controller) set to: {{selectedItemsReturnedFromDirective}} </p> 

    </body> 

</html> 

itemfilterTemplate.html

<select ng-model="selectedItems" multiple="multiple" style="height: 200px; width: 250px;" ng-change="selectedItemsChangedDir()" ng-options="item.id as item.name group by item.model for item in items | orderBy:'name'"> 
    <option>--</option> 
</select> 

app.js

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

app.directive('sdItemsFilter', function() { 
    return { 
    restrict: 'E', 
    scope: { 
     items: '=', 
     selectedItems: '=', 
     selectedItemsChanged: '&' 
    }, 
    templateUrl: "itemfilterTemplate.html", 
    link: function (scope, element, attrs){ 
     scope.selectedItemsChangedDir = function(){ 
     scope.selectedItemsChanged()(scope.selectedItems); 
     } 
    } 
    } 
}) 

app.controller('MainCtrl', function($scope) { 
    $scope.name = 'TARS'; 

    $scope.selectedItems = ["allItems"]; 

    $scope.selectedItemsChanged = function(selectedItems1) { 
    $scope.selectedItemsReturnedFromDirective = selectedItems1; 
    } 

    $scope.items = [{ 
    "id": "allItems", 
    "name": "All Items", 
    "order": 0 
    }, { 
    "id": "CaseItem", 
    "name": "Case Item", 
    "model": "PredefinedModel" 
    }, { 
    "id": "Application", 
    "name": "Application", 
    "model": "Bank" 
    }] 

}); 

作業plnkr:http://plnkr.co/edit/BSqx2J1yCY86IJwAnQF1?p=preview

オプション#5:NG-モデルと結合双方向を通じて、あなたは親スコープの変数を更新することができます。。したがって、親スコープ関数を呼び出す必要がない場合があります。

index.html

<!DOCTYPE html> 
<html ng-app="plunker"> 

    <head> 
    <meta charset="utf-8" /> 
    <title>AngularJS Plunker</title> 
    <script>document.write('<base href="' + document.location + '" />');</script> 
    <link rel="stylesheet" href="style.css" /> 
    <script data-require="[email protected]" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script> 
    <script src="app.js"></script> 
    </head> 

    <body ng-controller="MainCtrl"> 
    <p>Hello {{name}}!</p> 

    <p> Directive Content</p> 
    <sd-items-filter ng-model="selectedItems" selected-items-changed="selectedItemsChanged" items="items"> </sd-items-filter> 


    <P style="color:red">Selected Items (in parent controller) set to: {{selectedItems}} </p> 

    </body> 

</html> 

itemfilterTemplate.html

<select ng-model="selectedItems" multiple="multiple" style="height: 200px; width: 250px;" 
ng-options="item.id as item.name group by item.model for item in items | orderBy:'name'"> 
    <option>--</option> 
</select> 

app.js

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

app.directive('sdItemsFilter', function() { 
    return { 
    restrict: 'E', 
    scope: { 
     items: '=', 
     selectedItems: '=ngModel' 
    }, 
    templateUrl: "itemfilterTemplate.html" 
    } 
}) 

app.controller('MainCtrl', function($scope) { 
    $scope.name = 'TARS'; 

    $scope.selectedItems = ["allItems"]; 

    $scope.items = [{ 
    "id": "allItems", 
    "name": "All Items", 
    "order": 0 
    }, { 
    "id": "CaseItem", 
    "name": "Case Item", 
    "model": "PredefinedModel" 
    }, { 
    "id": "Application", 
    "name": "Application", 
    "model": "Bank" 
    }] 
}); 

作業plnkr:http://plnkr.co/edit/hNui3xgzdTnfcdzljihY?p=preview

オプション#6:$watch$watchCollection を通じて、それはすべて上記の例でitemsのために2つの結合方法である項目が親スコープに変更された場合、ディレクティブ内の項目も変更を反映することになります。

あなたが親スコープから他の属性やオブジェクトを見たい場合は、あなたが

htmlの下に与えられたとして$watch$watchCollectionを使用していることを行うことができます

<!DOCTYPE html> 
<html ng-app="plunker"> 

<head> 
    <meta charset="utf-8" /> 
    <title>AngularJS Plunker</title> 
    <script> 
    document.write('<base href="' + document.location + '" />'); 
    </script> 
    <link rel="stylesheet" href="style.css" /> 
    <script data-require="[email protected]" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script> 
    <script src="app.js"></script> 
</head> 

<body ng-controller="MainCtrl"> 
    <p>Hello {{user}}!</p> 
    <p>directive is watching name and current item</p> 
    <table> 
    <tr> 
     <td>Id:</td> 
     <td> 
     <input type="text" ng-model="id" /> 
     </td> 
    </tr> 
    <tr> 
     <td>Name:</td> 
     <td> 
     <input type="text" ng-model="name" /> 
     </td> 
    </tr> 
    <tr> 
     <td>Model:</td> 
     <td> 
     <input type="text" ng-model="model" /> 
     </td> 
    </tr> 
    </table> 

    <button style="margin-left:50px" type="buttun" ng-click="addItem()">Add Item</button> 

    <p>Directive Contents</p> 
    <sd-items-filter ng-model="selectedItems" current-item="currentItem" name="{{name}}" selected-items-changed="selectedItemsChanged" items="items"></sd-items-filter> 

    <P style="color:red">Selected Items (in parent controller) set to: {{selectedItems}}</p> 
</body> 

</html> 

スクリプトが

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

app.directive('sdItemsFilter', function() { 
    return { 
    restrict: 'E', 
    scope: { 
     name: '@', 
     currentItem: '=', 
     items: '=', 
     selectedItems: '=ngModel' 
    }, 
    template: '<select ng-model="selectedItems" multiple="multiple" style="height: 140px; width: 250px;"' + 
     'ng-options="item.id as item.name group by item.model for item in items | orderBy:\'name\'">' + 
     '<option>--</option> </select>', 
    link: function(scope, element, attrs) { 
     scope.$watchCollection('currentItem', function() { 
     console.log(JSON.stringify(scope.currentItem)); 
     }); 
     scope.$watch('name', function() { 
     console.log(JSON.stringify(scope.name)); 
     }); 
    } 
    } 
}) 

app.controller('MainCtrl', function($scope) { 
    $scope.user = 'World'; 

    $scope.addItem = function() { 
    $scope.items.push({ 
     id: $scope.id, 
     name: $scope.name, 
     model: $scope.model 
    }); 
    $scope.currentItem = {}; 
    $scope.currentItem.id = $scope.id; 
    $scope.currentItem.name = $scope.name; 
    $scope.currentItem.model = $scope.model; 
    } 

    $scope.selectedItems = ["allItems"]; 

    $scope.items = [{ 
    "id": "allItems", 
    "name": "All Items", 
    "order": 0 
    }, { 
    "id": "CaseItem", 
    "name": "Case Item", 
    "model": "PredefinedModel" 
    }, { 
    "id": "Application", 
    "name": "Application", 
    "model": "Bank" 
    }] 
}); 

いつでもディレクティブの詳細な説明については、AngularJsのドキュメントを参照してください。

+0

これは 'link'メソッドでラッパー関数を作成しました。スコープ関数をディレクティブ内の別のディレクティブに渡したときだけの問題でした。元の親コントローラ関数はまだ呼び出されましたが、あなたが示唆したようにそれをラップするまで 'arguments'は未定義でした。 – chovy

+0

私はサーバーからフェッチをトリガしなければならなかったので、リンク関数の例は、データを前後に渡す必要がなくても、ちょうどajax関数を呼び出すだけで済んだので、本当にうまく機能しました。あなたはそのような正確で十分な答えを得るために3票のように値する。 –

1

別のパターンがあります(角度1.5で動作します)。

angular.module('module', []) 
 

 
    .controller('MyController', function() { 
 

 
     var self = this; 
 
     self.msg = 0; 
 
     // implement directive event listener interface 
 
     this.onEvent = function(arg) { 
 
      self.msg++; 
 
     }; 
 
    }) 
 

 
    .directive('myDirective', function() { 
 
     return { 
 
      scope: { 
 
      data: '=', 
 
      handler: '=' 
 
      }, 
 
      template: '<button ng-click="handler.onEvent(data)">Emit event</button>' 
 
     } 
 
    });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script> 
 

 

 
<div ng-app="module" ng-controller="MyController as ctrl"> 
 
<my-directive handler="ctrl" data="'...received'"></my-directive> 
 
    {{ctrl.msg}} 
 
</div>

関連する問題