Not able to save row in Expandable row in Angular UI Grid
Asked Answered
A

3

6

I'm trying to use the row saving feature in combination with the expandable grid. The goal is to be able to save sub-grid rows, independently of the parent row.

$scope.gridOptions = {
  expandableRowTemplate: 'components/grid/orderLineTemplate.html',
  expandableRowHeight: 150,

  expandableRowScope: {
    subGridVariable: 'subGridScopeVariable'

  },
  columnDefs: [
    {field: '_id'},
    {field: 'number'}
  ]
};

$http.get(ORDER_API)
  .success(function (data) {
    for (var i = 0; i < data.length; i++) {
      var rowScope = data[i];
      rowScope.subGridOptions = {
        appScopeProvider: $scope,
        columnDefs: [
          {field: 'amount'},
          {field: 'packageAmount'},
          {field: 'carrierAmount'}
        ],
        data: rowScope.orderLines,
        saveRow : $scope.saveRow
      }
    }
    $scope.gridOptions.data = data;
  });

$scope.gridOptions.onRegisterApi = function (gridApi) {
  $scope.gridApi = gridApi;
  gridApi.rowEdit.on.saveRow($scope, $scope.saveRow);
};

$scope.saveRow = function (order) {
  var promise = $q.defer();
  $scope.gridApi.rowEdit.setSavePromise(order, promise.promise);
  if(order.number) {
    $http.put(ORDER_API + '/' + order._id, order).success(function () {
      promise.resolve();
    }).error(function () {
      promise.reject();
    });
  }

}
});

The saveRow function is called correctly when I edit a field in the parent row. When I edit a field in the sub-row, the following message appears in the console;
'A promise was not returned when saveRow event was raised, either nobody is listening to event, or event handler did not return a promise'
SaveRow is never called for the expanded sub-row.

Ararat answered 29/3, 2015 at 18:38 Comment(0)
C
3

You need to register the subgrid APIs. Each grid has its own separate API instance that you use to communicate with it:

rowScope.subGridOptions = {
  appScopeProvider: $scope,
  columnDefs: [
    {field: 'amount'},
    {field: 'packageAmount'},
    {field: 'carrierAmount'}
  ],
  data: rowScope.orderLines,
  saveRow : $scope.saveRow,
  onRegisterApi: function (gridApi) {
    gridApi.rowEdit.on.saveRow($scope, $scope.saveRow)
  }
}

That's close, but you're injecting our controller scope into the subgrid scope with appScopeProvider, which you don't really need to do. Instead, we can make saveRow generic and bind it to the gridApi we want. The first argument of bind() sets the this for the function. We'll just pass in the grid object, but we won't need it. The second argument to bind will be the gridApi we want to pass. Then in the saveRow definition we know we'll receive the right API as the first argument, and then the rowEntity as the second arg.

// Main grid:
$scope.gridOptions.onRegisterApi = function(gridApi) {
  gridApi.rowEdit.on.saveRow($scope, saveRow.bind(gridApi.grid, gridApi));
};

// Subgrids:
onRegisterApi: function(gridApi) {
  gridApi.rowEdit.on.saveRow($scope, saveRow.bind(gridApi.grid, gridApi));
}

// Altered saveRow:
function saveRow(gridApi, rowEntity) {
  var promise = $q.defer();
  gridApi.rowEdit.setSavePromise( rowEntity, promise.promise );

  // fake a delay of 3 seconds whilst the save occurs, return error if gender is "male"
  $interval( function() {
    if (rowEntity.gender === 'male' ){
      promise.reject();
    } else {
      promise.resolve();
    }
  }, 3000, 1);
};

Since you'll probably have a different save function for your subgrids the main thing to remember is to register the "saveRow" event on them all with onRegisterApi

Here's a working plunker demonstrating the code above: http://plnkr.co/edit/52mp9C?p=preview

Cohen answered 2/4, 2015 at 17:51 Comment(0)
A
2

If you use Angular $http or $resource, you needn't create any other 'deferred' objects, just return result:

$scope.saveRow = function (order) {
    // with use $http
    var promise = $http.put(ORDER_API + '/' + order._id, order);
    // or with use $resource
    var promise = $resource(ORDER_API + '/:id').save({ id: order._id }, order).$promise;
    $scope.gridApi.rowEdit.setSavePromise(order, promise);
    return promise;
  }
Ahmed answered 26/8, 2015 at 7:31 Comment(0)
L
1

You already created a deferred promise in you code. As error clearly says you need to return a promise, You should add return deferred.promise; to your code. I think you should also return a promise from else statement in order to get promise resolve/reject anyhow.

Code

$scope.saveRow = function(order) {
    var deferred = $q.defer();
    $scope.gridApi.rowEdit.setSavePromise(order, promise.promise);
    if (order.number) {
        $http.put(ORDER_API + '/' + order._id, order).success(function() {
            deferred.resolve();
        }).error(function() {
            deferred.reject();
        });
    } else {
        deferred.reject();
    }
    return deferred.promise; //this will return promise to caller function.
};

Hope this could help you, let me know if anything else is required. Thanks. :)

Lisp answered 5/4, 2015 at 8:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.