Reputation: 28563
I'm trying to allow a directive with an isolate scope to call a function on it's parent directive's scope. I've read numerous examples of using '&' notation in the directive's scope declaration to do this, but since the directive is used inside an ng-repeat and an ng-switch, scope inheritance seems to be thwarting me. The function doesn't seem to make it to my directive's scope.
I can get to the function by going up the parent chain ($scope.$parent.$parent.$parent.removeElement() works), but that feels gross. Is there a way around this?
Parent Directive:
function dynamicLayoutDirective($compile, $log, bevoLayoutEngine, layoutService) {
return {
restrict: 'ECMA',
replace: true,
templateUrl: 'templates/dynamicLayout.html',
scope: {
layoutSchema: '=',
layout: '=',
editMode: '='
},
controller: function($scope) {
$scope.removeElement = function(element) {
// This is the function I want to call
}
}
}
}
dynamicLayout.html
<div ng-repeat="element in layoutSchema">
<div ng-switch on="element.type">
<bevo-input ng-switch-when="TextBoxType" element="element" edit-mode="editMode" remove-element="removeElement"></bevo-input>
<bevo-datepicker ng-switch-when="DateType" element="element" edit-mode="editMode"></bevo-datepicker>
<bevo-section ng-switch-when="SectionType" element="element" edit-mode="editMode"></bevo-section>
</div>
</div>
Child directive:
angular.module('ngBevoInput', []).directive('bevoInput', function() {
return {
restrict: 'E',
templateUrl: 'templates/bevoInput.html',
scope: {
element: '=',
editMode: '=',
removeElement: '&'
},
controller: function($scope) {
$scope.remove = function() {
$scope.removeElement()({element: $scope.element});
// $scope.removeElement() returns undefined here.
// I can get to the function by doing $scope.$parent.$parent.$parent.removeElement
}
}
}
});
bevoInput.html
<div class="col-md-10 form-inline">
<input type="text" value="{{element.display}}" ng-hide="editMode" />
<input type="text" disabled ng-show="editMode" />
<button ng-show="editMode" ng-click="remove()" />
</div>
Upvotes: 1
Views: 211
Reputation: 49590
You have 2 bugs that I can see:
1) You are assigning the callback function incorrectly.
You are only passing the function name, but Angular expects an expression that invokes an outer-scope function, so add the parenthesis and pass the element
parameter.
<bevo-input remove-element="removeElement(element)"></bevo-input>
2) You are passing {element: $scope.element}
to the return value of $scope.removeElement
function. Remove the extra parenthesis.
$scope.removeElement({element: $scope.element});
EDIT:
Another issue I discovered has to do with the root element of the template having ng-repeat
AND the template has replace: true
. I'm not sure of the root cause (could be that the scope is lost), but to solve this, either (1) add another root, or (2) set replace: false
.
Upvotes: 1