Rani Radcliff
Rani Radcliff

Reputation: 5084

Angular ui-Grid Splice doesn't work with array

I have a ui-grid that I am trying to use to process bulk actions. Items should be removed from the grid once the action is completed. The problem is that the splice only works for every other record. The rest of the code works as expected, but not the splice. Every other record remains on the grid until I F5 to refresh the page (the backend functions actually delete the rows from the database - I was using splice to get a quicker view of the correct data without having to refresh the grid data once the database procedures complete).

Here is my controller code:

  $scope.gridOptions = {
        columnDefs: [
            {
                field: 'dteDateReleaseRequestedByCompany', displayName: 'Requested Date'
            },

      {
          field: 'vchCompanyName', displayName: 'Company Name',
          cellTemplate: '<div style="text-decoration:underline;color:blue;text-align:left;cursor:pointer" ng-click="grid.appScope.rowClick(row)">{{COL_FIELD}}</div>'
      },
      {
          field: 'CompanyID', width: 110, displayName: 'Company ID', visible:false
      },
      { field: 'vchOprCity', displayName: 'City' },
      { field: 'vchOprStateVchID', displayName: 'State' },
      {
          field: 'dteExpiresWithGracePeriod', displayName: 'Subscription', headerCellClass: 'center',
          cellTemplate: '<div style="text-align:center"><span ng-bind-html="row.entity[col.field] | getSubscription | trustedhtml"></span></div>'
      },
      {
          field: 'Action', displayName: 'Release Action', 
          cellTemplate: '<div class="btn-group" ng-init="row.entity.Action=0"><input ng-model="row.entity.Action" type="radio" value="0" style="width:20px">&nbsp;None&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input ng-model="row.entity.Action" type="radio" value="1" style="width:20px">&nbsp;Accept&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input ng-model="row.entity.Action" type="radio" value="2" style="width:20px">&nbsp;Decline</div>'

      },

        ],
        showGridFooter: false,
        //enableFiltering: true,
        enableSorting: false,
        paginationPageSizes: [20, 40, 60],
        paginationPageSize: 20,
        enableHorizontalScrollbar: uiGridConstants.scrollbars.NEVER,
        enableGridMenu: true,
        exporterCsvFilename: 'PendingReleases.csv',
        exporterPdfDefaultStyle: { fontSize: 9 },
        exporterPdfTableStyle: { margin: [10, 10, 10, 10] },
        exporterPdfTableHeaderStyle: { fontSize: 10, bold: true, italics: true, color: 'red' },
        exporterPdfHeader: { text: "Pending Release Requests", style: 'headerStyle' },
        exporterPdfFooter: function (currentPage, pageCount) {
            return { text: currentPage.toString() + ' of ' + pageCount.toString(), style: 'footerStyle' };
        },
        exporterPdfCustomFormatter: function (docDefinition) {
            docDefinition.styles.headerStyle = { fontSize: 22, bold: true, alignment: 'center' };
            docDefinition.styles.footerStyle = { fontSize: 10, bold: true, alignment: 'center' };
            return docDefinition;
        },
        exporterPdfOrientation: 'landscape',
        exporterPdfPageSize: 'LETTER',
        exporterPdfMaxGridWidth: 500,
        exporterCsvLinkElement: angular.element(document.querySelectorAll(".custom-csv-link-location")),
        onRegisterApi: function (gridApi) {
            $scope.gridApi = gridApi;

        }
    };

  $scope.process = function () {
        for (i = 0; i < $scope.gridOptions.data.length; i++)
        {
            var id = $scope.gridApi.grid.renderContainers.body.visibleRowCache[i].entity.CompanyID;
            var action = $scope.gridApi.grid.renderContainers.body.visibleRowCache[i].entity.Action;
            var index = i;

            if(action ==1)
            {
                $scope.gridOptions.data.splice(index, 1);

                accept(id, index);
            }
            if(action == 2)
            {
                $scope.gridOptions.data.splice(index, 1);

                decline(id, index);

            }

        }


    };

    function accept(id, index) {
        contractorService.acceptRelease(id);

    };
    function decline(id, index) {
        contractorService.declineRelease(id);

    };

Here is my HTML:

@{
    ViewBag.Title = "ManagePendingReleases";
    Layout = "~/Views/Shared/_Layout.cshtml";

}
<script src="~/Scripts/app/Contractor/ContractorCtrl.js"></script>
<script src="~/Scripts/app/Contractor/contractorService.js"></script>
<style>
    .ui-grid-header-cell {
  position: relative;
  box-sizing: border-box;
  color: black;
  background-color: #cfe7f1;
  border-right: 1px solid;
  border-color: #cfe7f1;
  display: table-cell;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  width: 0;
}
</style>
<div ng-app="myModule" ng-controller="ContractorCtrl">
    <div class="panel panel-primary">
        <div class="panel-heading" >Manage Pending Releases</div>
        <div class="panel-body" style="padding:0px">
            <div ui-grid="gridOptions" class="grid" ng-style="{height: (gridOptions.data.length*30)+32+'px'}" ui-grid-exporter ui-grid-auto-resize></div>
        </div>

    </div>
<div class="pull-right">
    <button type="button" class="btn btn-primary" ng-click="process()">Process Actions</button>
</div>
</div>

Here is what my grid looks like:

enter image description here

When the Process Actions button is clicked, it is supposed to iterate through the rows and find which Action should happen on each record in the database. When I step through the code it looks like the splice works for each record, but every other one remains on the grid. Can anyone tell why I am getting this behavior?

Any assistance is greatly appreciated!

Upvotes: 0

Views: 1749

Answers (2)

vinayakj
vinayakj

Reputation: 5681

You are using the length of array in for loop on which you are doing splice which in turn is reducing also you are using index to remove item, but splice is reducing the array, so index also needs to change.

So the closest plausible answer is, use delete instead of splice as delete doesn't change the index.

delete $scope.gridOptions.data[index]

Instead of

$scope.gridOptions.data.splice(index, 1);

Upvotes: 1

Emir Marques
Emir Marques

Reputation: 2687

Look this example. Notice how is excluded. The object of the index is obtained through a indexOf

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

app.controller('MainCtrl', ['$scope', '$log', function($scope, $log) {

  $scope.deleteRow = function(row) {
    var index = $scope.gridOptions.data.indexOf(row.entity);
    $scope.gridOptions.data.splice(index, 1);
  };

  $scope.gridOptions = {};

  $scope.gridOptions.columnDefs = [{
    name: 'firstName'
  }, {
    name: 'lastName'
  }, {
    name: 'Delete',
    cellTemplate: '<button class="btn primary" ng-click="grid.appScope.deleteRow(row)">Delete</button>'
  }];

  $scope.gridOptions.data = [{
    "firstName": "Cox",
    "lastName": "Carney",
    "company": "Enormo",
    "employed": true
  }, {
    "firstName": "Lorraine",
    "lastName": "Wise",
    "company": "Comveyer",
    "employed": false
  }, {
    "firstName": "Nancy",
    "lastName": "Waters",
    "company": "Fuelton",
    "employed": false
  }];

}]);
<!doctype html>
<html ng-app="app">
  <head>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-touch.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-animate.js"></script>
    <script src="http://ui-grid.info/docs/grunt-scripts/csv.js"></script>
    <script src="http://ui-grid.info/docs/grunt-scripts/pdfmake.js"></script>
    <script src="http://ui-grid.info/docs/grunt-scripts/vfs_fonts.js"></script>
    <script src="http://ui-grid.info/release/ui-grid.js"></script>
    <link rel="stylesheet" href="http://ui-grid.info/release/ui-grid.css" type="text/css">
    <link rel="stylesheet" href="main.css" type="text/css">
  </head>
  <body>

<div ng-controller="MainCtrl">
  <div ui-grid="gridOptions" class="grid"></div>
</div>


    <script src="app.js"></script>
  </body>
</html>

Upvotes: 0

Related Questions