Canttouchit Canttouchit - 20 days ago 17
AngularJS Question

Using ng-show to expand nested list on click

My code - Plunker

I used

ng-repeat
to render my nested
list
.
the
list
built in a way of a
folder
which is always displayed
and
files
which are displayed when parent
folder
is clicked.

The problem is when I use
ng-show
to display
files
all my
folders
are open
and not the clicked one only.

e.g

E.g

I want only the clicked record in the list to be expanded and not all records.
I understand why it happens and I'm looking for a way in
Angular
to solve this issue.
How can I achieve that?

My code

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

//controllers
webApp.controller ('VotesCtrl', function ($scope, Votes) {
$scope.votes = Votes;

$scope.show = false;

$scope.expand = function() {
console.log("show")
$scope.show = true;
}
});


//services


webApp.factory('Votes', [function() {

//temporary repository till integration with DB this will be translated into restful get query
var votes = [
{
id: '1',
created: 1381583344653,
updated: '222212',
ratingID: '4',
rate: 5,
ip: '198.168.0.0',
status: 'Approved',
folder:[
{
id: '1',
created: 1381583344653,
updated: '222212',
ratingID: '4',
rate: 5,
ip: '198.168.0.0',
status: 'Approved',
},
{
id: '111',
created: 1381583344653,
updated: '222212',
ratingID: '4',
rate: 5,
ip: '198.168.0.0',
status: 'Approved'
}
]
},
{
id: '2',
created: 1382387322693,
updated: '222212',
ratingID: '3',
rate: 1,
ip: '198.168.0.1',
status: 'Approved',
folder:[
{
id: '2',
created: 1382387322693,
updated: '222212',
ratingID: '3',
rate: 1,
ip: '198.168.0.1',
status: 'Approved',
},
{
id: '22',
created: 1382387322693,
updated: '222212',
ratingID: '3',
rate: 1,
ip: '198.168.0.1',
status: 'Approved'
},
{
id: '222',
created: 1382387327693,
updated: '222212',
ratingID: '3',
rate: 1,
ip: '198.168.0.1',
status: 'Approved'
},
]
},
{
file:[
{
id: '231',
created: 1392387327693,
updated: '222212',
ratingID: '1',
rate: 1,
ip: '198.168.2.1',
status: 'Approved'
}
]
}
];

return votes;
}]);


HTML

<div>
<ul>
<li class="created">
<b>CREATED</b>
</li>
<li class="ip">
<b>IP ADDRESS</b>
</li>
</ul>
<ul ng-repeat="vote in votes" ng-click="expand()">

<li class="created">
{{vote.created|date}}
</li>
<li class="ip">
{{vote.ip}}
</li>


<ul ng-show="show" ng-repeat="file in vote.folder">
<li class="created">
{{file.created|date}}
</li>
<li class="ip">
{{file.ip}}
</li>
</ul>
<ul class="file" ng-repeat="file in vote.file">
<li class="created">
{{file.created|date}}
</li>
<li class="ip">
{{file.ip}}
</li>
</ul>

</ul>

</div>

Answer

The behavior you are experiencing is normal. In the current state of your code there is only one show attribute and all your blocks are bound to this attribute. Modifying the value from false to true will result in refreshing all your blocks. Show attribute being set to true everything will be expanded.

What you need to do is for every votes add an attributes show and bound the show/hide state to this attribute. Something like :

<ul ng-repeat="vote in votes" ng-click="expand(vote)">
  <li class="created">{{vote.created|date}}</li>
  <li class="ip">{{vote.ip}}</li>
  <li ng-show="vote.show">
    <ul>
      <li  ng-repeat="file in vote.folder">

And your expand function will look like :

$scope.expand = function(vote) {
   vote.show = true;
}

See the modified Plunker here : http://plnkr.co/edit/gRtg4157Z3kDbNpejvFW?p=preview