Reputation: 23
Please refer to this AngularJS example at plunker or at the code below
My first question:
In the accordion directive at line 40, why is the scope variable "expanders" reinitialized to an empty array as follows var expanders = [];
after it was initialized originally in the SomeController at line 20?
My second question:
why they passed the directive scope at line 70 and 74 and not the element ?
as follows:
line 70: accordionController.addExpander(scope);
line 74: accordionController.gotOpened(scope);
My third question: i moved all the code from the accordion controller to the link function of the expander directive and the app still working 100% , why they built the expanders array on the parent accordion directive if they could built it in the link function of the expander ? please refer to this new plunk
.expander {
border: 1px solid black;
margin: 1px;
width: 250px;
}
.expander > .title {
background-color: black;
color: white;
padding: .1em .3em;
cursor: pointer;
}
.expander > .body {
padding: .1em .3em;
}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html ng-app='appModule'>
<head>
<title>Accordion</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js"></script>
<link href="accordion.css" rel='stylesheet'>
</head>
<body ng-controller='SomeController' >
<accordion>
<expander class='expander'
ng-repeat='expander in expanders'
expander-title='expander.title'>
{{expander.text}}
</expander>
</accordion>
</body>
<script>
function SomeController($scope) {
$scope.expanders = [
{title: 'Click me to expand',
text: 'Hi there folks, I am the content that was hidden but is now shown.'},
{title: 'Click this',
text: 'I am even better text than you have seen previously'},
{title: 'No, click me!',
text: 'I am text that should be seen before seeing other texts'}
];
}
var appModule = angular.module('appModule', []);
appModule.directive('accordion', function() {
return {
restrict: 'EA',
replace: true,
transclude: true,
template: '<div ng-transclude></div>',
controller: function() {
var expanders = [];
this.gotOpened = function(selectedExpander) {
angular.forEach(expanders, function(expander) {
if (selectedExpander != expander) {
expander.showMe = false;
}
});
}
this.addExpander = function(expander) {
expanders.push(expander);
}
}
}
});
appModule.directive('expander', function(){
return {
restrict: 'EA',
replace: true,
transclude: true,
require: '^?accordion',
scope: { title:'=expanderTitle' },
template: '<div>' +
'<div class="title" ng-click="toggle()">{{title}}</div>' +
'<div class="body" ng-show="showMe" ng-transclude></div>' +
'</div>',
link: function(scope, element, attrs, accordionController) {
scope.showMe = false;
accordionController.addExpander(scope);
scope.toggle = function toggle() {
scope.showMe = !scope.showMe;
accordionController.gotOpened(scope);
}
}
}
});
</script>
</html>
Upvotes: 2
Views: 382
Reputation: 849
`$scope.expanders` is only visible in the scope of `SomeController`
while var expander
in directive is local variable in directive it self.
Don't get confused with bothof them. Take it as they have nothing to do with each other.
<body ng-controller='SomeController' >
<accordion>
<expander class='expander'
ng-repeat='expander in expanders' <!-- expanders here refers to $scope.expanders in SomeController that has some data in it -->
expander-title='expander.title'>
{{expander.text}}
</expander>
</accordion>
</body>
Answer for Question 2
Because they are passing the title of expander to addExpander()
function.
scope: { title:'=expanderTitle' }
. They have defined scope like this in
expander directive
and in scope
the have given title
Answer for Question 3
That is what general and preferred practice is. You just cannot(should not) put everything in a single function.
Upvotes: 1