0

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!

15
  • Need all the relevant code to understand whats going on, plz add it. Commented Nov 17, 2015 at 19:19
  • Try this $scope.gridOptions.data = $scope.gridOptions.data.splice(index, 1); Commented Nov 17, 2015 at 19:19
  • @EmirMarques splice changes the original array so doesnt matter. Commented Nov 17, 2015 at 19:20
  • @vinayakj right, but angular can generate this problem Commented Nov 17, 2015 at 19:25
  • @EmirMarques splice is pure javascript API, how come angular's object be any different than javascript object. Commented Nov 17, 2015 at 19:27

2 Answers 2

1

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);
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! Works perfectly!
0

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>

1 Comment

Yes, but that example is passing in a row object on a click event on a particular row. I'm not passing in a row object because I am processing all rows at once.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.