问题
I have used https://github.com/angular-ui/bootstrap for accordion, but with this directive I'm having scope issues. It only allows to use scope if ngController is declared inside of accordion.
Please visit below two Plunker links and you will understand what I'm trying to say:
Example 1: http://plnkr.co/edit/Fb4UauWWmHOnTyjMPFBo
index.html
<!doctype html>
<html ng-app="plunker">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular-animate.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.13.4.js"></script>
<script src="script.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="AccordionDemoCtrl">
<accordion>
<accordion-group is-open="status.open">
<accordion-heading>
Accordian - Click me <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': status.open, 'glyphicon-chevron-right': !status.open}"></i>
</accordion-heading>
<div>
<input type="checkbox" ng-model="select" ng-click="checkAll()" /> Check me
</div>
</accordion-group>
</accordion>
</div>
</body>
</html>
script.js
var app = angular.module('plunker', ['ui.bootstrap']);
app.controller('AccordionDemoCtrl', function($scope) {
$scope.checkAll = function() {
alert($scope.select);
};
});
Example 2: http://plnkr.co/edit/ljEMUnTqPBqUyub5eEB7
index.html
<!doctype html>
<html ng-app="plunker">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular-animate.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.13.4.js"></script>
<script src="script.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<accordion>
<accordion-group is-open="status.open">
<accordion-heading>
Accordian - Click me <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': status.open, 'glyphicon-chevron-right': !status.open}"></i>
</accordion-heading>
<div ng-controller="AccordionDemoCtrl">
<input type="checkbox" ng-model="select" ng-click="checkAll()" /> Check me
</div>
</accordion-group>
</accordion>
</body>
</html>
script.js
var app = angular.module('plunker', ['ui.bootstrap']);
app.controller('AccordionDemoCtrl', function($scope) {
$scope.checkAll = function() {
alert($scope.select);
};
});
回答1:
I found the solution:
We can pass the value from the function itself, not necessary to access value using $scope.
Demo: http://plnkr.co/edit/fZZrDN4e8kbvimR2Wzya
index.html
<!doctype html>
<html ng-app="plunker">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular-animate.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.13.4.js"></script>
<script src="script.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="AccordionDemoCtrl">
<accordion>
<accordion-group is-open="status.open">
<accordion-heading>
Accordian - Click me <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': status.open, 'glyphicon-chevron-right': !status.open}"></i>
</accordion-heading>
<div>
<input type="checkbox" ng-model="select" ng-click="checkAll(select)" /> Check me
</div>
</accordion-group>
</accordion>
</div>
</body>
</html>
script.js:
var app = angular.module('plunker', ['ui.bootstrap']);
app.controller('AccordionDemoCtrl', function($scope) {
$scope.checkAll = function (select) {
alert(select);
};
});
回答2:
This is happening because the scope
of directive
"accordionGroup
" in Angular Bootstrap is isolated
and the $scope
of controller
"AccordionDemoCtrl
" is inherited using require
in a "directive
".
So, for Example1 when you try to access the $scope
binding of AccordionDemoCtrl
inside the accordian group
directive
, it is easily accessible. But as the select
is in local
scope
of accordian group
directive
it is not accessible in the controller.
So, for Example2 when you try to access the $scope
binding of AccordionDemoCtrl
inside the accordian group directive
it is easily accessible as the controller is in the local scope
for the accordian group
.
Please refer directive to directive Comm.
This is code from the Angular Bootstrap Library for Accordian
.directive('accordion', function () {
return {
restrict:'EA',
controller:'AccordionController',
transclude: true,
replace: false,
templateUrl: 'template/accordion/accordion.html'
};
})
// The accordion-group directive indicates a block of html that will expand and collapse in an accordion
.directive('accordionGroup', function() {
return {
require:'^accordion', // We need this directive to be inside an accordion
restrict:'EA',
transclude:true, // It transcludes the contents of the directive into the template
replace: true, // The element containing the directive will be replaced with the template
templateUrl:'template/accordion/accordion-group.html',
scope: {
heading: '@', // Interpolate the heading attribute onto this scope
isOpen: '=?',
isDisabled: '=?'
},
controller: function() {
this.setHeading = function(element) {
this.heading = element;
};
},
link: function(scope, element, attrs, accordionCtrl) {
accordionCtrl.addGroup(scope);
scope.$watch('isOpen', function(value) {
if ( value ) {
accordionCtrl.closeOthers(scope);
}
});
scope.toggleOpen = function() {
if ( !scope.isDisabled ) {
scope.isOpen = !scope.isOpen;
}
};
}
};
})
// Use accordion-heading below an accordion-group to provide a heading containing HTML
// <accordion-group>
// <accordion-heading>Heading containing HTML - <img src="..."></accordion-heading>
// </accordion-group>
.directive('accordionHeading', function() {
return {
restrict: 'EA',
transclude: true, // Grab the contents to be used as the heading
template: '', // In effect remove this element!
replace: true,
require: '^accordionGroup',
link: function(scope, element, attr, accordionGroupCtrl, transclude) {
// Pass the heading to the accordion-group controller
// so that it can be transcluded into the right place in the template
// [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]
accordionGroupCtrl.setHeading(transclude(scope, function() {}));
}
};
})
来源:https://stackoverflow.com/questions/32604689/issue-in-angular-bootstrap-directive-while-trying-to-access-scope