Remove edited record from Kendo Grid after remote Update is completed & prevent multiple update API calls for a single update

2 posts, 1 answers
  1. Dayanand
    Dayanand avatar
    4 posts
    Member since:
    Apr 2015

    Posted 08 Jun 2016 Link to this post

    I have a Kendo UI Grid who's data is being read from a table T1. However, all other Create/Update/Delete operations are being saved to another table T2 along with a field/column 'Operation'. The purpose is to allow an authorized user to review those changes before approving them and updating the record in the original table T1. Therefore, any client-side create/update/delete operation results only an 'insert' operation into table T2. Now here the requirement is that once the server performs its task (inserting the updated model into table T2), the client should remove the model/row/record from the Kendo UI Grid. So once the server completes it's api call it returns the same model back to the client. And on the client-side I am handling the kendo dataSource's requestEnd event to remove the model from the grid. Below code shall give a better idea:

    Kendo UI Grid Options:

    ctrl.whtRatesMasterGridOptions = {
                dataSource: {
                    type: 'odata',
                    transport: {
                        read: {
                            url: 'api/WHTRatesMaster',
                            dataType: 'json',
                            cache: false
                        },
                        create: {
                            url: 'api/WHTRatesMasterPendingChange',
                            dataType: "json"
                        },
                        update: {
                            url: 'api/WHTRatesMasterPendingChange',
                            dataType: "json",
                            type: "POST"
                        },
                        destroy: {
                            url: 'api/WHTRatesMasterPendingChange',
                            dataType: "json",
                            contentType: "application/json",
                            type: "POST"
                        },
                        parameterMap: function (options, type) {
                            if (type !== "read" && options) {
                                options.Operation = type;
                                return kendo.stringify(options);
                            }
                        }
                    },
                    requestEnd: function (e) {  // ctrl.currentModelUid is set in the grid's edit event.
                        if (e.type === "create" || e.type === "update") {      // since kendo itself remove's a deleted record from the grid we are only remove the model in case of a 'create' or 'update' operation
                            var currentModel = ctrl.whtRatesMasterGrid.dataSource.getByUid(ctrl.currentModelUid);
                            ctrl.whtRatesMasterGrid.dataSource.remove(currentModel);
                        }
                    },
                    schema: {
                        data: function (data) {
                            if ('Items' in data)
                                return data.Items;
                            return data;
                        },
                        total: function (data) {
                            return data.Count ? data.Count : 0;
                        },
                        model: {
                            id: "PortfolioCountryEffectiveDateKey",
                            fields: {
                                PortfolioCountryEffectiveDateKey: { type: "string", editable: false, nullable: false },
                                Portfolio: { type: "string", editable: true, nullable: false, validation: { required: true } },
                                Iso3Code: { type: "string", editable: true, nullable: false, validation: { required: true } },
                                EffectiveDate: { type: "date", editable: true, nullable: false, validation: { required: { message: "Effective Date is required" } } },
                                // some more model fields....
                            }
                        }
                    },
                },
                edit: function (e) {
                    ctrl.currentModelUid = e.model.uid;
                },
            };

     

    The 'PortfolioCountryEffectiveDateKey' is simply a concatenation of the Portfolio, Iso3Code & the EffectiveDate fields - the server sends it when grid performs a read operation. The database tables have a composite key on these three columns, but since kendo does not have a concept of specifying composite key, I have used such a concatenated property to allow kendo uniquely identify a record in its dataSource by the model.id configuration.

    Server-side API:

    [Route("api/WHTRatesMasterPendingChange")]
            [ResponseType(typeof(WHTRatesMasterPendingChange))]
            public IHttpActionResult WHTRatesMasterPendingChange(WHTRatesMasterPendingChange whtRatesMasterPendingChange)
            {
        // dbcontext.dbset.Add(whtRatesMasterPendingChange)
        return Ok(whtRatesMasterPendingChange);
            }

    The signature of the Read API:

    public PageResult<WHTRatesMaster> GetWHTRatesMasterDbSet(ODataQueryOptions options, [FromODataUri]bool showActivePortfolios)

    Here both the WHTRatesMaster & WHTRatesMasterPendingChange models have a the same composite identity fields (Portfolio, Iso3Code, EffectiveDate).
    Problem: The desired functionality ('inserting' records into the table T2 & removing the record from the kendo grid) works well for the CREATE & DESTROY operation. However, when I try to update records, the first request is successful, but for the second request two API calls are made (the first is success, second fails because kendo sends the same model again to the server) - which results in a primary key violation constraint error. So how to I solve the problem of kendo making the same API call twice.
    (TO BE NOTED : I am using the same server-side API and type:POST for Create, Update, & Destroy)
    EDIT: If I remove the 'requestEnd' event handler, then only single API calls are made to the server. But I also need to remove the updated row from the grid; so don't think I can do away with this event.

  2. Answer
    Boyan Dimitrov
    Admin
    Boyan Dimitrov avatar
    2062 posts

    Posted 09 Jun 2016 Link to this post

    Hello Dayanand,

    The main idea of CRUD operations is to be performed against single data base. When the updated/newly created item is returned by the server (update/create action method) the DataSource performs some internal logic to update the data item state. Removing the item in the requestEnd event might not work as expected since there might be a conflict with the DataSource's internal logic. 

    However since the T1 is not updated at all (all updates are handled to the T2)  my suggestion is to try to call read method of the DataSource in order to display the old state of the grid instead of removing items. 

    Regards,
    Boyan Dimitrov
    Telerik
     
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
     
Back to Top