4

I have an ng-repeat which has a button that has a function that toggles an ng-show element inside that ng-repeat.

The inside the class movie_option span has an ng-click=toggleInfo($index):

And the div additional_info has an ng-show that shows or hides an element.

    <ul ng-cloak="showResult">
        <li class="search_results" ng-repeat="movie in movies | orderBy: '-release_date'  track by $index">
            <div class="movie_info">
                <div class="movie_options">
                    <div class="slide">
                        <span class="movie_option">
                            <span><i class="fa fa-question-circle" aria-hidden="true" ng-click="toggleInfo($index)"></i></span>
                        </span>
                    </div>
                </div>
            </div>
            <div class="additional_info" ng-show="hiddenDiv[$index]">
                {{movie.overview}}
            </div>
        </li>
    </ul>

When a user clicks on the icon it calls this function:

    $scope.toggleInfo = function (index) {
         $scope.hiddenDiv[index] = !$scope.hiddenDiv[index];
    }

This toggles the ng-show state from the hiddenDiv ng-show. This works fine.

What I wanted to do is put all hiddenDiv states on false except the one that is clicked so only one ng-show would be true.

kukkuz
  • 41,512
  • 6
  • 59
  • 95
Peter Boomsma
  • 8,851
  • 16
  • 93
  • 185

3 Answers3

6

That's a pure algorithm problem, not related to Angular.

Instead of having a boolean per item, it would be much simpler to just remember the element (index) that should be displayed:

<ul ng-cloak="showResult">
    <li class="search_results" ng-repeat="movie in movies | orderBy: '-release_date'  track by $index">
        <div class="movie_info">
            <div class="movie_options">
                <div class="slide">
                    <span class="movie_option">
                        <span><i class="fa fa-question-circle" aria-hidden="true" ng-click="model.displayedIndex = $index"></i></span>
                    </span>
                </div>
            </div>
        </div>
        <div class="additional_info" ng-show="$index === model.displayedIndex">
            {{movie.overview}}
        </div>
    </li>
</ul>

And in your controller $scope.model = {}

Fiddle: http://jsfiddle.net/6dkLqgfL/

floribon
  • 19,175
  • 5
  • 54
  • 66
  • I've tried this but it doesn't seem to get the expected result. When I have 10 li elements, how does clicking on the in one affect the others without an function? Isn't the click contained into that li (ng-repeat)? – Peter Boomsma Aug 01 '16 at 14:01
  • `ng-click="displayedIndex = $index"` is an expression. You don't need to call a function but can directly execute code. If you prefer, you can write `ng-click="onlyDisplay($index)"` and then in your scope add the function `$scope.onlyDisplay = function(idx) { $scope.displayedIndex = idx; }` – floribon Aug 01 '16 at 15:43
  • @PeterBoomsma and actually after testing it it is safer to not use directly $scope.displayedIndex but have it as a property $scope.something.displayedIndex for instance (otherwise the behavior depends on your version of Angular). Check that working fiddle: http://jsfiddle.net/6dkLqgfL/ – floribon Aug 01 '16 at 15:51
  • Thank you, looks like a really clean sollution. When a user clicks on the icon it sets the index of the repeat on the `model.displayedIndex` then the ng-show checks if the current $index is equal to model.displayedIndex, if so sets it to true. Is that a correct assumption? What I find "weird" about this how does clicking in on ng-repeat affect the other ng-repeat elements? – Peter Boomsma Aug 02 '16 at 07:25
1

I think this would do:

$scope.toggleInfo = function(index) {
     for(var i in $scope.hiddenDiv) {
         if(index != i)
             $scope.hiddenDiv[i] = false;
     }
     $scope.hiddenDiv[index] = !$scope.hiddenDiv[index];

}
kukkuz
  • 41,512
  • 6
  • 59
  • 95
0

You could just manually turn all the hiddenDiv elements to false when the toggleInfo function is fired.

$scope.toggleInfo = function(index){
  for(int i = 0; i<($scope.hiddenDiv).length; i++)
    $scope.hiddenDiv[i] = false;

  $scope.hiddenDiv[index] = !$scope.hiddenDiv[index];
}

See if this works?

Zeokav
  • 1,653
  • 4
  • 14
  • 29