Saving row data with AngularJS ui-grid $scope.saveRow

All we need is an easy explanation of the problem, so here it is.

I’m working on a small frontend application which will show various product shipping data in a ui-grid.

I have the following code:

HTML:

<body ng-controller="MyCtrl">

    <p ng-repeat="row in myData">{{row.name}} works at {{row.company}}</p>

    <button type="button" class="btn btn-success" ng-click="getCurrentFocus()">Get Current focused cell</button>  <span ng-bind="currentFocused"></span>
    <br/>
    <br/>
    <div id="grid1" ui-grid="gridOptions" external-scopes="editRows" ui-grid-edit ui-grid-row-edit ui-grid-pinning ui-grid-paging ui-grid-cellnav class="grid"></div>

</body>

AngularJS:

var app = angular.module('webapps', ['ngAnimate', 'ui.grid', 'ui.grid.edit', 'ui.grid.rowEdit', 'ui.grid.pinning', 'ui.grid.paging', 'ui.grid.cellNav']);

app.controller('MyCtrl', ['$scope', '$http', '$q', '$interval', function ($scope, $http, $q, $interval) {

 //Column definitions
    $scope.columns = [
        { field: 'name', displayName: 'First Name', width: 300},
        { field: 'lastname', displayName: 'Last Name', width: 300 },
        { field: 'email', displayName: 'Email', width: 300 },
        { field: 'company', displayName: 'Company', width: '50%' }
    ];

    //Options for displaying the grid
    $scope.gridOptions = {
        data: 'myData',
        enableCellEditOnFocus: false,
        pagingPageSizes: [2, 5, 7],
        pagingPageSize: 5,
        enableSorting: true,
        enableGridMenu: true,
        columnDefs: $scope.columns,
        onRegisterApi: function (gridApi) {
            $scope.gridApi = gridApi;
            //var cellTemplate = '<button class="btn primary" ng-click="getExternalScopes().showMe(rowCol.row.entity)">Edit</button>'; //'ui-grid/selectionRowHeader';   // you could use your own template here
            //$scope.gridApi.core.addRowHeaderColumn({ name: 'rowHeaderCol', displayName: '', width: 50, pinnedLeft: true, cellTemplate: cellTemplate });
            gridApi.rowEdit.on.saveRow($scope, $scope.saveRow);
        }
    };

    // Save row data on edit 1 - TESTING
    $scope.saveRow = function (rowEntity) {
        // create a fake promise - normally you'd use the promise returned by $http or $resource
        var promise = $http.post("Webapps/Home/SaveRow");
        $scope.gridApi.rowEdit.setSavePromise($scope.gridApi.grid, rowEntity, promise.promise);
        console.log(rowEntity);

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

My question is in regards to the $scope.saveRow method. I’ve looked over the documentation here and tried searching on google (not much out there for ui-grid) but I’m still hitting a dead end as I’m a bit inexperienced with this and I’m not sure how to code this properly with promises.

There will be an MVC app running behind this which will handle pushing the data to the front end and saving table edits to a SQLServer db. Obviously what I’d like to do is have this $scope.saveRow function properly send the rowEnttiy data back to my MVC app but, again, I’m at a loss for how to code the function. The “fake” promises included in the example aren’t enough for me to get a grasp on what I need to do, apparently. I initially tried the following:

$scope.saveRow = function (rowEntity) {
    try {
        // Need actual URL for post...controller has to accept 'row'
        $http.post("Webapps/Home/SaveRow", { row: rowEntity }).success(function (data, status, headers, config) {
            console.log("post success");
            console.log(rowEntity);
        }).error(function (data, status, headers, config) {
            console.log("post failure");
            console.log(rowEntity);
        });
    } catch (e) {
        alert("Something went wrong");
    }
};

but this only throws an exception in my console that a promise was not returned when the saveRow event is raised.

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

You would normally do the promise/api call in a separate repository, but basically the code you are looking for is something like this:

 $scope.saveRow = function( rowEntity ) {

    var promise = $scope.someRepositoryFunction(rowEntity);
    $scope.gridApi.rowEdit.setSavePromise($scope.gridApi.grid, rowEntity, promise);

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

$scope.someRepositoryFunction = function(row) {
    return $http.put('/Home/UpdateRow',row);
}

Method 2

I’m not allowed to comment so I have to submit an answer. The answer above is incorrect in that the $scope.gridApi.grid parameter to teh setSavePromise function is NOT required. Although the function does require a grid parameter, it is added by the wrapper during the .apply call.

Method 3

I had actually used the code submitted by punkologist and it was indeed working but there seemed to be errors in the console on resolving promise after including $interval.

I guess the following is the appropriate code to make it run error free. Hope it works.

$scope.saveRow = function( rowEntity ) {

var promise = $q.defer();
$http.put('/Home/UpdateRow',row).success(function(){
$interval(function(){
     promise.resolved();
     },3000, 1)
}).error(promise.reject);

$scope.gridApi.rowEdit.setSavePromise($scope.gridApi.grid, rowEntity, promise);
};

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply