Search code examples
angularjsangularjs-ng-repeatng-showng-hide

Ng-click ng-show/ng-hide for a list of buttons created by ng-repeat


I have a list of play/pause buttons created by an ng-repeat. You click each play button to stream a song and the button turns into a pause button (so you can then pause it). I was able to get the buttons and click events set up correctly but ran into the problem of when you click one play button, all the buttons change to pause buttons.

play buttons pause buttons

I (think I) get why this is happening: because the ng-show variable (visible) is being changed and that therefore affects all of them.

I read through other similar answers on this (ng-repeat ng-show dilemna) but I haven't been able to apply the lessons (such as using $index) to my example. Also, many of the examples and fiddles use a div that you click which then does something like show = !show which then in turn shows a "loading..." .

I think mine's a bit different.

Here's my html:

<div class="nav nav-stacked list-group-item" id="sidebar" ng-repeat="show in shows"> 

                <div class="media col-md-3">

                    <img class="media-object img-rounded img-responsive" src="/images/play_button.png" alt="playbutton" height="40px" width="40px" ng-click="streamTrack(show.stream_url)" ng-show="visible">
                    <img class="media-object img-rounded img-responsive" src="/images/pause_button.png" alt="playbutton" height="40px" width="40px" padding-right="5px" ng-click="pauseTrack(sound)" ng-hide="visible">

                </div>
        </div>

Here's the relevant part of my controller:

$scope.visible = true;

$scope.streamTrack = function (stream_url) {
    SC.stream(stream_url, function (sound) {
    $scope.sound = sound;
    sound.play();
    });

    $scope.visible = false;

};

$scope.pauseTrack = function (sound) {
    sound.pause();
    $scope.visible = true;
};

What are some ways to handle this? So that when you click on one play button, it hides just than play button and exposes the pause button for only that one. I'm guessing it's probably something with $index or Parentindex but after a couple hours of messing around and reading, I'm still not getting closer.


Solution

  • You're applying visible to all of the objects when you need to only apply them to each object like so:

        function sampleController($scope){
    
            $scope.songs = [
                {title:'song1',visible:true,url:'url-song-1'},
                {title:'song2',visible:true,url:'url-song-2'}
            ];
    
            $scope.playTrack = function(s) {
                SC.stream(s.stream_url, function (sound) {
                  $scope.sound = sound;
                  sound.play();
                });
                s.visible = false;
            };
    
            $scope.pauseTrack = function(s) {
                s.visible = true;
            };
        }
    
        <div ng-controller="sampleController">
            <ul>
                <li ng-repeat="s in songs">
                    {{s.title}}
                    <button ng-click="playTrack(s)" ng-show="s.visible">Play</button>
                    <button ng-click="pauseTrack(s)" ng-show="!s.visible">Pause</button>
                </li>
            </ul>
        </div>