I\'m looking for any manner of accessing the \"parent\" scope within a directive. Any combination of scope, transclude, require, passing in variables (or the scope itself)
Accessing controller method means accessing a method on parent scope from directive controller/link/scope.
If the directive is sharing/inheriting the parent scope then it is quite straight forward to just invoke a parent scope method.
Little more work is required when you want to access parent scope method from Isolated directive scope.
There are few options (may be more than listed below) to invoke a parent scope method from isolated directives scope or watch parent scope variables (option#6 specially).
Note that I used link function in these examples but you can use a directive controller as well based on requirement.
Option#1. Through Object literal and from directive html template
index.html
AngularJS Plunker
Hello {{name}}!
Directive Content
Selected Items (in parent controller) set to: {{selectedItemsReturnedFromDirective}}
itemfilterTemplate.html
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"
}]
});
working plnkr: http://plnkr.co/edit/rgKUsYGDo9O3tewL6xgr?p=preview
Option#2. Through Object literal and from directive link/scope
index.html
AngularJS Plunker
Hello {{name}}!
Directive Content
Selected Items (in parent controller) set to: {{selectedItemsReturnedFromDirective}}
itemfilterTemplate.html
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({selectedItems: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"
}]
});
working plnkr: http://plnkr.co/edit/BRvYm2SpSpBK9uxNIcTa?p=preview
Option#3. Through Function reference and from directive html template
index.html
AngularJS Plunker
Hello {{name}}!
Directive Content
Selected Items (in parent controller) set to: {{selectedItemsReturnFromDirective}}
itemfilterTemplate.html
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"
}]
});
working plnkr: http://plnkr.co/edit/Jo6FcYfVXCCg3vH42BIz?p=preview
Option#4. Through Function reference and from directive link/scope
index.html
AngularJS Plunker
Hello {{name}}!
Directive Content
Selected Items (in parent controller) set to: {{selectedItemsReturnedFromDirective}}
itemfilterTemplate.html
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"
}]
});
working plnkr: http://plnkr.co/edit/BSqx2J1yCY86IJwAnQF1?p=preview
Option#5: Through ng-model and two way binding, you can update parent scope variables.. So, you may not require to invoke parent scope functions in some cases.
index.html
AngularJS Plunker
Hello {{name}}!
Directive Content
Selected Items (in parent controller) set to: {{selectedItems}}
itemfilterTemplate.html
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"
}]
});
working plnkr: http://plnkr.co/edit/hNui3xgzdTnfcdzljihY?p=preview
Option#6: Through $watch and $watchCollection
It is two way binding for items in all above examples, if items are modified in parent scope, items in directive would also reflect the changes.
If you want to watch other attributes or objects from parent scope, you can do that using $watch and $watchCollection as given below
html
AngularJS Plunker
Hello {{user}}!
directive is watching name and current item
Id:
Name:
Model:
Directive Contents
Selected Items (in parent controller) set to: {{selectedItems}}
script app.js
var app = angular.module('plunker', []);
app.directive('sdItemsFilter', function() {
return {
restrict: 'E',
scope: {
name: '@',
currentItem: '=',
items: '=',
selectedItems: '=ngModel'
},
template: '',
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"
}]
});
You can always refer AngularJs documentation for detailed explanations about directives.