Isolated scope for items inside ng repeat in direc

2019-07-27 06:19发布

问题:

I'm trying to create a directive where in data is displayed in a table layout. Each row has a edit button and on clicking the edit button only that row should be in edit mode. But in my case all the rows get displayed in edit mode. Here is demo.

Here is the directive code :

.directive('myGrid', function() {
  return {
    restrict: 'E',
    scope: {
      employees: '='
    },
    controller: function($scope) {
      $scope.isEdit = false;

      $scope.showEdit = function() {
        $scope.isEdit = $scope.isEdit == true ? false : true;
      }
    },
    template: '<table class="table">' +
      '<thead>' +
      '<tr>' +
      '<th ng-repeat="(key,value) in employees[0]">{{key}}</th>' +
      '</tr>' +
      '</thead>' +
      '<tbody>' +
      '<tr ng-repeat="emp in employees">' +
      '<td><span ng-hide="isEdit">{{emp.FirstName}}</span><input type="text" ng-show="isEdit" ng-model="emp.FirstName" class="form-control"></td>' +
      '<td><span ng-hide="isEdit">{{emp.LastName}}</span><input type="text" ng-show="isEdit" ng-model="emp.LastName" class="form-control"></td>' +
      '<td><span ng-hide="isEdit">{{emp.Email}}</span><input type="text" ng-show="isEdit" ng-model="emp.Email" class="form-control"></td>' +
      '<td><span ng-click="showEdit()" ng-class="{\'glyphicon glyphicon-edit\':isEdit==false,\'glyphicon glyphicon-ok\':isEdit==true}"></span></td>' +
      '</tr>' +
      '</tbody>' +
      '</table>'
  };
})

回答1:

 angular
    .module('myApp', [])
    .controller('myCtrl', ['$scope', function($scope) {
        $scope.employees = [{
            'FirstName': 'Jay',
            'LastName': 'Raj',
            'Email': 'jay3dec@gmail.com'
        }, {
            'FirstName': 'Roy',
            'LastName': 'Mathews',
            'Email': 'roymathews@gmail.com'
        }];
        $scope.employees.forEach(function(employee) {
            employee.isEdit = false;
        });
    }])
    .directive('myGrid', function() {
        return {
            restrict: 'E',
            scope: {
                employees: '='
            },
            controller: function($scope) {
                $scope.showEdit = function(emp) {
                    emp.isEdit = !emp.isEdit;
                };
            },
            template: '<table class="table">' +
                '<thead>' +
                '<tr>' +
                '<th ng-repeat="(key,value) in employees[0]">{{key}}</th>' +
                '</tr>' +
                '</thead>' +
                '<tbody>' +
                '<tr ng-repeat="emp in employees">' +
                '<td><span ng-if="!emp.isEdit">{{emp.FirstName}}</span><input type="text" ng-if="emp.isEdit" ng-model="emp.FirstName" class="form-control"></td>' +
                '<td><span ng-if="!emp.isEdit">{{emp.LastName}}</span><input type="text" ng-if="emp.isEdit" ng-model="emp.LastName" class="form-control"></td>' +
                '<td><span ng-if="!emp.isEdit">{{emp.Email}}</span><input type="text" ng-if="emp.isEdit" ng-model="emp.Email" class="form-control"></td>' +
                '<td><span ng-click="showEdit(emp)" ng-class="{\'glyphicon glyphicon-edit\':emp.isEdit==false,\'glyphicon glyphicon-ok\':emp.isEdit==true}"></span></td>' +
                '</tr>' +
                '</tbody>' +
                '</table>'
        };
    });
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp">
    <div class="container" ng-controller="myCtrl">
      <my-grid employees="employees"></my-grid>
    </div>
</body>



回答2:

Yosvel solution is fine and is admittedly the simplest.

Nevertheless, I created an alternative based on the $index of the ng-repeat. One could also keep track of which item is being modified instead of the $index.

Demo

angular.module('myApp', [])

.controller('myCtrl', ['$scope', function($scope) {
  $scope.employees = [{
    'FirstName': 'Jay',
    'LastName': 'Raj',
    'Email': 'jay3dec@gmail.com'
  }, {
    'FirstName': 'Roy',
    'LastName': 'Mathews',
    'Email': 'roymathews@gmail.com'
  }];
}])

.directive('myGrid', function() {
  return {
    restrict: 'E',
    scope: {
      employees: '='
    },
    controller: function($scope) {

      $scope.indexBeingEdited = -1;

      $scope.showEdit = function($index) {
        if($scope.indexBeingEdited === $index) {
          // second click... stop edit 
          $scope.indexBeingEdited = -1;
          return;
        }
        $scope.indexBeingEdited = $index;
      };
      $scope.isEdit = function($index) {
        return $index === $scope.indexBeingEdited;
      };
    },
    templateUrl: '/myGrid.html'
  };
})

<body ng-app="myApp">
  <div class="container" ng-controller="myCtrl">
    <my-grid employees="employees"></my-grid>
  </div>
</body>


<script type="text/ng-template" id="/myGrid.html">
  <table class="table">
    <thead>
      <tr>
        <th ng-repeat="(key,value) in employees[0]">{{key}}</th>
      </tr>
    </thead>
    <tbody>
      <tr ng-repeat="emp in employees">
        <td>
          <span ng-hide="isEdit($index)">{{emp.FirstName}}</span>
          <input type="text" ng-show="isEdit($index)" ng-model="emp.FirstName" class="form-control">
        </td>
        <td>
          <span ng-hide="isEdit($index)">{{emp.LastName}}</span>
          <input type="text" ng-show="isEdit($index)" ng-model="emp.LastName" class="form-control">
        </td>
        <td>
          <span ng-hide="isEdit($index)">{{emp.Email}}</span>
          <input type="text" ng-show="isEdit($index)" ng-model="emp.Email" class="form-control">
        </td>
        <td>
          <span ng-click="showEdit($index)" class="glyphicon" ng-class="{' glyphicon-edit':isEdit($index)===false,'glyphicon-ok':isEdit($index)===true}"></span>
        </td>
      </tr>
    </tbody>
  </table>
</script>


回答3:

try like this

angular.module('myApp', [])

.controller('myCtrl', ['$scope', function($scope) {
  $scope.employees = [{
    'FirstName': 'Jay',
    'LastName': 'Raj',
    'Email': 'jay3dec@gmail.com'
  }, {
    'FirstName': 'Roy',
    'LastName': 'Mathews',
    'Email': 'roymathews@gmail.com'
  }];
}])

.directive('myGrid', function() {
  return {
    restrict: 'E',
    scope: {
      employees: '='
    },
    controller: function($scope) {
      $scope.isEdit = -1;

      $scope.showEdit = function(index) {
       
       $scope.isEdit = $scope.isEdit == index ? -1 : index;
      }
    },
    template: '<table class="table">' +
      '<thead>' +
      '<tr>' +
      '<th ng-repeat="(key,value) in employees[0]">{{key}}</th>' +
      '</tr>' +
      '</thead>' +
      '<tbody>' +
      '<tr ng-repeat="emp in employees">' +
      '<td><span ng-show="isEdit != $index">{{emp.FirstName}}</span><input type="text" ng-show="isEdit == $index" ng-model="emp.FirstName" class="form-control"></td>' +
      '<td><span ng-show="isEdit != $index">{{emp.LastName}}</span><input type="text" ng-show="isEdit == $index" ng-model="emp.LastName" class="form-control"></td>' +
      '<td><span ng-show="isEdit != $index">{{emp.Email}}</span><input type="text" ng-show="isEdit == $index" ng-model="emp.Email" class="form-control"></td>' +
      '<td><span ng-click="showEdit($index)" ng-class="{\'glyphicon glyphicon-edit\':isEdit != $index,\'glyphicon glyphicon-ok\':isEdit == $index}"></span></td>' +
      '</tr>' +
      '</tbody>' +
      '</table>'
  };
})
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
  <div class="container" ng-controller="myCtrl">
    <my-grid employees="employees"></my-grid>
  </div>
</div>