5

I have a ng-repeat which display a list of divs and when I click on one it shows an aditionnal div for the clicked item.

This is working

<div ng-repeat="item in items">

    <div ng-click="showfull = !showfull">
        <div>
            <h1>{{item.title}}</h1>
            <p>{{item.content}}</p>
        </div>
    </div>
    <div ng-show="showfull">
        <p>{{item.info}}</p>
    </div>
    <hr/>
</div>

My items are loaded from a json containing a list of item and each item have a default attribut showfull set to false in this json. This is working, but now I want to hide all others item in the list when an item is clicked. I've tryied something like this :

This is not working

<div ng-repeat="item in items">

    <div ng-click="expand(item)">
        <div>
            <h1>{{item.title}}</h1>
            <p>{{item.content}}</p>
        </div>
    </div>
    <div ng-show="showfull">
        <p>{{item.info}}</p>
    </div>
    <hr/>
</div>

and in the controller I've added a function :

$scope.expand = function(e) {
    e.showfull = !e.showfull;
    //TODO: put here a foreach logic to hide all other items
}

But even without the foreach logic this is not working, the item don't show the additionnal div when clicked. I have two question :

  1. I suppose this is due to item being "passed by copy" in the expand function or some kind of scope isolation issue but can you explain me why in detail ? SOLVED

  2. How can I hide all the additional div of other items when I click an item and show the additionnal content for this item ? Do I need to do a directive ? NOT SOLVED

Thanks

dekajoo
  • 2,024
  • 1
  • 25
  • 36

3 Answers3

4

I think you're on the right track. You need to set the showfull on the item and then use ng-show or ng-if to hide it, or as Gavin mentioned, use a class.

On ng-click you can call your expand function, where you pass the item, toggle it and set all others to hidden.

Template:

<div ng-repeat="item in items>
    <div ng-click="expand(item)">
        <div>
            <h1>{{item.title}}</h1>
            <p>{{item.content}}</p>
        </div>
    </div>
    <div ng-show="item.showfull">
        <p>{{item.info}}</p>
    </div>
    <hr/>
</div>

Controller:

$scope.expand = function (item) {
    angular.forEach($scope.items, function (currentItem) {
        currentItem.showfull = currentItem === item && !currentItem.showfull;
    });
};
PzYon
  • 2,963
  • 3
  • 16
  • 27
2

Your expand method is modifying the item, so your ng-show needs to reference the item:

<div ng-show="item.showfull">
    <p>{{item.info}}</p>
</div>

To hide all of your items you need to do something like

$scope.expand = function(item) {
   angular.forEach(items, function(i) {
       if (i === item) {
           i.showfull = !i.showfull;
       } else {
           i.showfull = false;
       }
    });
};
Vadim
  • 17,897
  • 4
  • 38
  • 62
  • Thanks that seems to work, what happen if I don't reference the item in the angular point of view? Angular don't link item to the ng-show action ? – dekajoo Oct 16 '14 at 15:58
  • @deKajoo if you don't reference the item, you would be going against `$scope.showfull` – Vadim Oct 16 '14 at 15:59
  • Second question : to hide all other items should I use `angular.forEach` in the controller function or is there a better way? (edit: thanks for the first answer) – dekajoo Oct 16 '14 at 15:59
0

Shouldn't the second div you want to show be referencing the item?

<div ng-repeat="item in items>

    <div ng-click="expand(item)">
        <div>
            <h1>{{item.title}}</h1>
            <p>{{item.content}}</p>
        </div>
    </div>
    <!-- Added item to ng-show -->
    <div ng-show="item.showfull"> 
        <p>{{item.info}}</p>
    </div>
    <hr/>
</div>
Oliver
  • 35,233
  • 12
  • 66
  • 78