2

Using ng-repeat I want to use ng-model and ng-show to subjectively select an area to expand for the purpose of updating pet, place or points. Right now, it shows for all p in Pets within ng-repeat but I only want it to show for the single p's update button that is clicked. Extra points if you can show me how to close it when the update button is clicked again. Here is my html with Angularjs directives:

<table>
<thead>
       <tr>
           <th colspan="1" class="text-center">
             Pets, Places and Points   
           </th>
           <th colspan="1" class="text-center">
              Update
           </th>
       <tr>
<thead>

<tbody filter-list="search"ng-repeat="p in Pets">

<tr>

   <td class="col-xs-6 col-sm-6 col-md-6 col-xl-6 merchant">
        {{p.pet}}, {{p.place}} and {{p.points}}
   </td>

    <td class="col-xs-4 col-sm-4 col-md-4 col-xl-4 update">
        <button ng-click="show()">Update</button>
        <br>
        <div ng-show="showing">
             <input  placeholder= "Pets" ng-model="Pets"/>
             <br>
             <input  placeholder= "Places" ng-model="Places"/>
             <br>
             <input  placeholder= "Points" ng-model="Points"/>
             <br>
             <button  ng-click="Update(Pets, Places, Points)">Enter</button>
         </div>       
    </td>
</tr>

</tbody>
</table>

The show(); function

$scope.show = function() {
      console.log("show")
      $scope.showing = true;
    }
rashadb
  • 2,515
  • 4
  • 32
  • 57

1 Answers1

3

Sometimes, going back to basics works the best. Since we know each iteration in ng-repeat creates a new scope, in order to avoid using the inherited show function, a simple showing != showing should work (even though it's undefined by default, it's fine since that's a falsy value, but you can always initialize it as well).

See it here:

angular.module('app', [])
.controller('Ctrl', function($scope) {
  $scope.Pets = [
    {pet: 1, place: 1, points: 1},
    {pet: 2, place: 2, points: 2},
    {pet: 3, place: 3, points: 3}
  ];
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="Ctrl">
  <table>
    <thead>
      <tr>
        <th colspan="1" class="text-center">
          Pets, Places and Points
        </th>
        <th colspan="1" class="text-center">
          Update
        </th>
        <tr>
          <thead>

            <tbody ng-repeat="p in Pets">

              <tr>

                <td class="col-xs-6 col-sm-6 col-md-6 col-xl-6 merchant">
                  {{p.pet}}, {{p.place}} and {{p.points}}
                </td>

                <td class="col-xs-4 col-sm-4 col-md-4 col-xl-4 update">
                  <button ng-click="showing = !showing">Update</button>
                  <br>
                  <div ng-show="showing">
                    <input placeholder="Pets" ng-model="Pets" />
                    <br>
                    <input placeholder="Places" ng-model="Places" />
                    <br>
                    <input placeholder="Points" ng-model="Points" />
                    <br>
                    <button ng-click="Update(Pets, Places, Points)">Enter</button>
                  </div>
                </td>
              </tr>

            </tbody>
  </table>
</div>

If you don't like this approach and want to use one common function (there are reasons you'd do that, but I don't see them in your example), you can use ng-repeat indices, and then do something like:

$scope.show = function(i) {
  console.log("showing " + i)
  $scope.showing[i] = true;
}

And simply invoke it like this:

<button ng-click="show($index)">Update</button>

and control the visibility like this:

<div ng-show="showing[$index]">

See it here:

angular.module('app', [])
.controller('Ctrl', function($scope) {
  $scope.showing = [];
  $scope.Pets = [
    {pet: 1, place: 1, points: 1},
    {pet: 2, place: 2, points: 2},
    {pet: 3, place: 3, points: 3}
  ];
  $scope.toggle = function(i) {
    console.log("show")
    $scope.showing[i] = !$scope.showing[i];
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="Ctrl">
  <table>
    <thead>
      <tr>
        <th colspan="1" class="text-center">
          Pets, Places and Points
        </th>
        <th colspan="1" class="text-center">
          Update
        </th>
        <tr>
          <thead>

            <tbody ng-repeat="p in Pets">

              <tr>

                <td class="col-xs-6 col-sm-6 col-md-6 col-xl-6 merchant">
                  {{p.pet}}, {{p.place}} and {{p.points}}
                </td>

                <td class="col-xs-4 col-sm-4 col-md-4 col-xl-4 update">
                  <button ng-click="toggle($index)">Update</button>
                  <br>
                  <div ng-show="showing[$index]">
                    <input placeholder="Pets" ng-model="Pets" />
                    <br>
                    <input placeholder="Places" ng-model="Places" />
                    <br>
                    <input placeholder="Points" ng-model="Points" />
                    <br>
                    <button ng-click="Update(Pets, Places, Points)">Enter</button>
                  </div>
                </td>
              </tr>

            </tbody>
  </table>
</div>
Shomz
  • 37,421
  • 4
  • 57
  • 85
  • 1
    I can't give bonus but damn that was a good look. I'll probably be able to apply the second example to additional use cases. – rashadb Apr 28 '15 at 01:07
  • Yeah, the first one is more of a quick fix (still works fine, but you might lose control of it at some point), but the second one is the way to go (was too lazy to write it at first, ended up writing both...). – Shomz Apr 28 '15 at 01:11