Night Watcher
Night Watcher

Reputation: 41

How enable multiple row selection in angular js table

I created html table and used ng-repeat to show items in table, but i can't select multiple rows in table. How can achieve this by using control key Thank you!

<div class="table_bg">
<table datatable="ng" dt-options="dtOptions" dt-column-defs="dtColumnDefs" class="table table-striped table-bordered dt-responsive nowrap res_table" cellspacing="0" width="100%">
    <thead>
        <tr>
            <th>#</th>
            <th>Description</th>
            <th>Ali</th>
            <th> Extension</th>
            <th> Ext/th>
            <th>Comp</th>
        </tr>
    </thead>
    <tbody ng-hide="loading">
        <tr ng-class="{'selected':$index == selectedRow}" ng-click="setClickedRow($index)" ng-repeat="docType in DocTypes" ng-cloak ng-mouseenter="hover(docType)" ng-mouseleave="hover(docType)">
            <td>{{$index}}</td>
            <td>

                {{docType.Desc}}
            </td>
            <td>{{docType.LI}}</td>
            <td>{{docType.Ext}}</td>
            <td>{{docType.EXT}}</td>
            <td>{{docType.Comp}}</td>
        </tr>
    </tbody>
</table>

Upvotes: 4

Views: 18979

Answers (3)

Maher
Maher

Reputation: 2547

In this sample i try to detect which row is selected, so i add selected param to the each object which already selected, and then we can use $filter to detect the selected rows.

var app = angular.module("app", []);
app.controller("ctrl", function($scope, $filter) {
  $scope.users = [{
    name: "x"
  }, {
    name: "y"
  }, {
    name: "z"
  }];
  
  $scope.selectedRows = [];

  $scope.select = function(item) {
    item.selected ? item.selected = false : item.selected = true;
  }

  $scope.getAllSelectedRows = function() {
    var selectedRows = $filter("filter")($scope.users, {
      selected: true
    }, true);
    
    $scope.selectedRows = selectedRows;
  }

});
body {
  padding-top: 50px;
}

tr td {
  cursor: pointer
}

tr.selected td {
  background: #ccc!important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-rc.0/angular.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />

<div ng-app="app" ng-controller="ctrl">
  <div class="container">
    <table class="table table-bordered">
      <tr ng-repeat="user in users" ng-class="{'selected': user.selected}" ng-click="select(user)">
        <td ng-bind="user.name" title="click to select a row"></td>
      </tr>
    </table>

    <button class="btn btn-primary" ng-click="getAllSelectedRows()">Get All Selected Rows</button>
    
    {{selectedRows | json}}
  </div>
</div>

Upvotes: 6

CredibleAshok
CredibleAshok

Reputation: 73

This demo uses Ctrl, Shift and combination of both for multiple selection of table rows in angularJs. For plnkr demo.

http://plnkr.co/edit/IGBCkLpmK4ecJ9RUsALa?p=preview

Html goes like this

<!DOCTYPE html>
<html ng-app="app">

  <head>
    <script data-require="angular.js@*" data-semver="4.0.0" src="https://code.angularjs.org/latest/angular.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-controller="multiSelectController as vm">
    {{vm.a}}
      <table>
      <thead>
      </thead>
      <tbody style="border:1px solid blue;">
        <tr ng-repeat="item in vm.externalProductsTypes" ng-click="vm.selectUnselectMultiple($index,$event)" ng-class="{'selected': vm.isRowSelectedUnselect($index)}">
          <td  style="border:1px solid blue;">{{item.id}}</td>
          <td  style="border:1px solid blue;">
            <div style="float:left;  margin-right: 10px;">{{item.name}}</div>
          </td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

controller goes like this

var app = angular.module('app', []);

app.controller('multiSelectController', function() {
  var vm = this;
  /* Data loading */
  vm.externalProductsTypes = [{
    "id":1,
    "name": "Access Winback"
  }, {
    "id":2,
    "name": "ADSL",
  }, {
    "id":3,
    "name": "Bigpond ADSL Activation",
  }, {
    "id":4,
    "name": "Bigpond ADSL Recontracting",
  }, {
    "id":5,
    "name": "Bigpond Cable Activation",
  }, {
    "id":6,
    "name": "Bigpond Cable Recontracting",
  }, {
    "id":7,
    "name": "Bigpond VAS",
  }, {
    "id":8,
    "name": "Bigpond Wireless Activation",
  }, {
    "id":9,
    "name": "Bigpond Wireless Recontracting",
  }, {
    "id":10,
    "name": "Broadband Right Plan",
  }];
  /* click function */
  vm.selectUnselectMultiple = function (idx, event) {

            if (event.which != '1') {
                return;
            }

            var row = vm.externalProductsTypes[idx];
            row.rowIndex = idx;

            if (!event.ctrlKey && !event.shiftKey) {
                vm.clearAll();
                vm.toggleRow(row);
                vm.selectionPivot = row;
                return;
            }
            if (event.ctrlKey && event.shiftKey) {
                vm.selectRowsBetweenIndexes(vm.selectionPivot.rowIndex, row.rowIndex);
                return;
            }
            if (event.ctrlKey) {
                vm.toggleRow(row);
                vm.selectionPivot = row;
            }
            if (event.shiftKey) {

                vm.clearAll();
                vm.selectRowsBetweenIndexes(vm.selectionPivot.rowIndex, row.rowIndex);
            }
        }
        /* other supported functions */
        vm.toggleRow = function (row) {
            row.className = row.className == 's' ? '' : 's';
        }

        vm.selectRowsBetweenIndexes = function (ia, ib) {
            var bot = Math.min(ia, ib);
            var top = Math.max(ia, ib);

            for (var i = bot; i <= top; i++) {
                vm.externalProductsTypes[i].className = 's';
            }
        }

        vm.clearAll = function () {
            for (var i = 0; i < vm.externalProductsTypes.length; i++) {
                vm.externalProductsTypes[i].className = '';
            }
        }

        vm.isRowSelectedUnselect = function (index) {
            if (vm.externalProductsTypes[index].className=='s') { // if found, then select the row.
                return true;
            }
        }
});

finally the css for row selection

.selected {
    background-color: steelblue !important;
    color: white;
    font-weight: bold;
}

Upvotes: 0

I hope this is not too late for you, I have you answer.

You can use the $event.ctrlKey parameter to check if the user has pressed control.

Even better, there is a $event.shiftKey parameter to check if shift was pressed.

You can use it this way, (I let all the logic in a simple controller so that it is easier to understand but I advice you to put it inside a service). Also I have chosen to store only the rows index but it works the same with full rows.

HTML

<tr ng-repeat="row in rows track by $index" ng-click="selectRow($event, $index)" ng-class="{highlitedRow: isRowSelected($index)}">

AngularJS

var selectedRowsIndexes = [];
$scope.rows = [{name: 'Happy Butterfly'}, {name: 'Wonderful Bee'}];


$scope.selectRow = function(event, rowIndex) {
  if(event.ctrlKey) {
      changeSelectionStatus(rowIndex);
  } else if(event.shiftKey) {
      selectWithShift(rowIndex);
  } else {
      selectedRowsIndexes = [rowIndex];
  }
  console.log(selectedRowsIndexes);
  console.log(getSelectedRows());
  console.log(getFirstSelectedRow());
};

function selectWithShift(rowIndex) {
  var lastSelectedRowIndexInSelectedRowsList = selectedRowsIndexes.length - 1;
  var lastSelectedRowIndex = selectedRowsIndexes[lastSelectedRowIndexInSelectedRowsList];
  var selectFromIndex = Math.min(rowIndex, lastSelectedRowIndex);
  var selectToIndex = Math.max(rowIndex, lastSelectedRowIndex);
  selectRows(selectFromIndex, selectToIndex);
}

function getSelectedRows() {
  var selectedRows = [];
  angular.forEach(selectedRowsIndexes, function(rowIndex) {
    selectedRows.push($scope.rows[rowIndex]);
  });
  return selectedRows;
}

function getFirstSelectedRow() {
  var firstSelectedRowIndex = selectedRowsIndexes[0];
  return $scope.rows[firstSelectedRowIndex];
}

function selectRows(selectFromIndex, selectToIndex) {
  for(var rowToSelect = selectFromIndex; rowToSelect <= selectToIndex; rowToSelect++) {
    select(rowToSelect);
  }
}

function changeSelectionStatus(rowIndex) {
  if($scope.isRowSelected(rowIndex)) {
      unselect(rowIndex);
  } else {
      select(rowIndex);
  }
}

function select(rowIndex) {
  if(!$scope.isRowSelected(rowIndex)) {
      selectedRowsIndexes.push(rowIndex)
  }
}

function unselect(rowIndex) {
  var rowIndexInSelectedRowsList = selectedRowsIndexes.indexOf(rowIndex);
  var unselectOnlyOneRow = 1;
  selectedRowsIndexes.splice(rowIndexInSelectedRowsList, unselectOnlyOneRow);
}

function resetSelection() {
  selectedRowsIndexes = [];
}

$scope.isRowSelected = function(rowIndex) {
  return selectedRowsIndexes.indexOf(rowIndex) > -1;
};

});

Last thing, if you want to use powerfull tables, I recommend you ng-table.

If you use ng-table, be sure to add

$scope.$on('ngTableAfterReloadData', function() {
  resetSelection();
});

and replace $scope.rows[rowIndex] with $scope.tableParams.data[rowIndex]

Upvotes: 9

Related Questions