Handling updates : alternative to full datasource read following successful CRUD

12 posts, 1 answers
  1. Gary
    Gary avatar
    9 posts
    Member since:
    Sep 2016

    Posted 18 Oct Link to this post

    All of our CRUD via inline grid / popups are being  are being followed by a full read of the datasource to keep things in synch (please see sample transport code).

    I know this full refresh of the datasource is not necessary. I am trying to understand what is required :

    1) Following a successful deletion do I need to delete a row from the grid and datasource and how?

    2) Following a successful update do I need to set reset dirty flags to false? Anything else?

    3) Following a successful insert how do return extract new key id value and use to synch grid and datasource ?

     

     

    transport:
    {
        read: function (options) {
            $.ajax({
                url: siteUrlRel  + "/Handlers/GenericHandler.aspx?sp=sp_getAddresses",
                dataType: "json",
                type: "GET",
                cache: false,
                contentType: "application/json; charset=utf-8",
                success: function (result) {
                    options.success(result);
                }
            });
        },
        create: function (options) {
            $.ajax({
                url: siteUrlRel  + "/Handlers/GenericCRUDHandler.aspx?sp=sp_addAddress",

                data: encodePlus(kendo.stringify(options.data)),
                dataType: "json",
                async: false,
                type: "POST",
                success: function (response) {
                    addressesDataSource.read();
                },
                error: function (response) {
                    alert(response);
                    addressesDataSource.cancelChanges();
                }
            });
        },
        update: function (options) {
            $.ajax({
                url: siteUrlRel  + "/Handlers/GenericCRUDHandler.aspx?sp=sp_updateAddress",

                data: encodePlus(kendo.stringify(options.data)),
                async: false,
                dataType: "json",
                type: "POST",
                success: function (response) {
                    addressesDataSource.read();
                    UpdateMessage("Addresses changes applied");
                }
            });
        },
        destroy: function (options) {
            $.ajax({
                url: siteUrlRel  + "/Handlers/GenericCRUDHandler.aspx?sp=sp_deladdresses",
                   data:encodePlus(kendo.stringify(options.data)),
                async: false,
                type: "POST",
                success: function (response) {
                    addressesDataSource.read();
                },
                error: function (response) {
                    alert(response.responseText);
                    addressesDataSource.cancelChanges();
                }
            });
        },
        parameterMap: function (options, operation) {
            if (operation !== "read" && options.models) {
                return { models: kendo.stringify(options.models) };
            }
        }
    },

  2. Stefan
    Admin
    Stefan avatar
    268 posts

    Posted 19 Oct Link to this post

    Hello Gary,

    Regarding the read method which is call on every create, update and delete- this is not necessary as the Grid will be updated automatically, this includes the data and the UI. In fact, this is making unnecessary calls to the remote server and can cause performance issues.

    Regarding the three question: These will be made automatically by the Grid if the remote service is implemented correctly.

    I can suggest checking the information for the CRUD data operations:

    http://docs.telerik.com/kendo-ui/framework/datasource/crud 

    Also, check our demo examples for the editable Grid:

    http://demos.telerik.com/kendo-ui/grid/editing-inline 

    I hope this is helpful.

    Regards,
    Stefan
    Telerik by Progress
     
    Build rich, delightful, *native* Angular 2 apps with Kendo UI for Angular 2. Try it out today! Kendo UI for Angular 2 (currently in beta) is a jQuery-free toolset, written in TypeScript, designed from the ground up to offer true, native Angular 2 components.
     
  3. Kendo UI is VS 2017 Ready
  4. Gary
    Gary avatar
    9 posts
    Member since:
    Sep 2016

    Posted 01 Nov Link to this post

    Hi Stefan,

    I know for the create, update and delete operations to work automatically the remote service needs to return data the same as expected by the read. In our case we do not return data like this. We either return an error message (if there is any) or new id (in the case of a create). I need our remote database access code to remain like this otherwise it will mean major changes.

    Please can you provide examples how I can manually deal with create, update and delete operations in our case.

    regards,

    Gary

     

  5. Stefan
    Admin
    Stefan avatar
    268 posts

    Posted 03 Nov Link to this post

    Hello Gary,

    If the data format is different than the expected one, I can suggest using the schema.parse property of the DataSource to preprocess the data from the server and parse it on the client, and the parameterMap property to modify the result from the client before sending it to the server:

    http://docs.telerik.com/kendo-ui/api/javascript/data/datasource#configuration-schema.parse

    http://docs.telerik.com/kendo-ui/api/javascript/data/datasource#configuration-transport.parameterMap 

    If you still need to implement custom CRUD operations and our assistance is needed, please send an example so we can offer a suggestion best suited for it.

    Regards,
    Stefan
    Telerik by Progress
     
    Build rich, delightful, *native* Angular 2 apps with Kendo UI for Angular 2. Try it out today! Kendo UI for Angular 2 (currently in beta) is a jQuery-free toolset, written in TypeScript, designed from the ground up to offer true, native Angular 2 components.
     
  6. Gary
    Gary avatar
    9 posts
    Member since:
    Sep 2016

    Posted 03 Nov in reply to Stefan Link to this post

    Stefan,

    I have given you a revised code example from the one at the at the start of this post. It includes the data model. I am not sure what else I can provide you with that would help.

     

    At the moment the response from CRUD operations is a database error message if any is raised otherwise on response we don't send back any other data. We should be able to easily to change this to send back the id value (in the example address_id) of the record involved (which would be essential for an create operation but not sure it would be necessary for and update or destroy?). This would allow to complete the sychronisation on the client side. I am assuming we need some alternative some code in the success functions for create, update and destroy?

     

    If you could provide some generic pseudo code how to handle this that would be great.

     

    var addressesDataSource = new kendo.data.DataSource(
    {
        transport:
        {
            read: function (options) {
                $.ajax({
                    url: siteUrlRel + "/Handlers/GenericHandler.aspx?sp=sp_getAddresses",
                    dataType: "json",
                    type: "GET",
                    cache: false,
                    contentType: "application/json; charset=utf-8",
                    success: function (result) {
                        options.success(result);
                    }
                });
            },
            create: function (options) {
                $.ajax({
                    url: siteUrlRel + "/Handlers/GenericCRUDHandler.aspx?sp=sp_addAddress",
     
                    data: encodePlus(kendo.stringify(options.data)),
                    dataType: "json",
                    async: false,
                    type: "POST",
                    success: function (response) {
                        addressesDataSource.read();
                    },
                    error: function (response) {
                        alert(response);
                        addressesDataSource.cancelChanges();
                    }
                });
            },
            update: function (options) {
                $.ajax({
                    url: siteUrlRel + "/Handlers/GenericCRUDHandler.aspx?sp=sp_updateAddress",
     
                    data: encodePlus(kendo.stringify(options.data)),
                    async: false,
                    dataType: "json",
                    type: "POST",
                    success: function (response) {
                        addressesDataSource.read();
                        UpdateMessage("Addresses changes applied");
                    }
                });
            },
            destroy: function (options) {
                $.ajax({
                    url: siteUrlRel + "/Handlers/GenericCRUDHandler.aspx?sp=sp_deladdresses",
                    data: encodePlus(kendo.stringify(options.data)),
                    async: false,
                    type: "POST",
                    success: function (response) {
                        addressesDataSource.read();
                    },
                    error: function (response) {
                        alert(response.responseText);
                        addressesDataSource.cancelChanges();
                    }
                });
            },
            parameterMap: function (options, operation) {
                if (operation !== "read" && options.models) {
                    return { models: kendo.stringify(options.models) };
                }
            }
        },
        batch: true,
     
        serverSorting: true,
        schema: {
            model: {
                id: "address_id",
                fields: {
                    address_id: { type: "number" },
                    place: { type: "string", validation: { required: true, required: { message: "Company name is required" } } },
                    country_id: {
                        type: "number",
                        validation: {
                            requiredropdown_countryDropDownEditor: function (input) {
                            return AddDropDownValidationUniqueMessageName(input, "countryDropDownEditor", "Country is required");
                            }
     
                        }
                    },
                    postcode: { type: "string", validation: { required: true } },
                    state: { type: "string", validation: { required: false } },
                    city: { type: "string", validation: { required: true } },
                    address_line1: { type: "string" },
                    address_line2: { type: "string" },
                    address_line3: { type: "string" },
                    address_type_id: {
                        type: "number",
                        validation: {
                            requiredropdown_address_type_editor: function (input) {
                            return AddDropDownValidationUniqueMessageName(input, "address_type_editor", "Require address type");
                            }
                        }
                    },
                    addressDetails: { type: "string" },
                    country: { type: "string" }
     
                }
            },
            parse: function (response) {
                $.each(response, function (idx, elem) {
     
     
                    elem.addressDetails = elem.place + ", " + getCountryName(elem.country_id) + ", " + elem.postcode;
                    // elem.country = getCountryName(elem.country_id);
                });
                return response;
            }
        }
    });
  7. Stefan
    Admin
    Stefan avatar
    268 posts

    Posted 07 Nov Link to this post

    Hello Gary,

    After inspecting the provided code snippet, I can assume that the issue occurs because in the success function the read method is trying to be executed before the previous request is finished. Also, the example is using synchronised Ajax requests.

    I can suggest instead of using the read method in the success function, to use the requestEnd event of the dataSource to call the read() method of the dataSource. Please have in mind to check the type of the request, to ensure that the read method will not be called when the initial request is read as this will create infinite loop:

    http://docs.telerik.com/kendo-ui/api/javascript/data/datasource#events-requestEnd

    requestEnd:function(e){
     if(e.type != 'read'){
      dataSource.read();
      }
     }

    I hope this will help to achieve the desired result.

    Regards,
    Stefan
    Telerik by Progress
     
    Build rich, delightful, *native* Angular 2 apps with Kendo UI for Angular 2. Try it out today! Kendo UI for Angular 2 (currently in beta) is a jQuery-free toolset, written in TypeScript, designed from the ground up to offer true, native Angular 2 components.
     
  8. Gary
    Gary avatar
    9 posts
    Member since:
    Sep 2016

    Posted 07 Nov in reply to Stefan Link to this post

    Stefan,

    Regarding your latest post - I am unsure what issue you addressing here. I think you have sent us a fix for a different issue?

     

    Please can reread all posts from my original on the 6th September. To summarise - after create, update and destroy operations we currently reread the data - addressesDataSource.read() which we know is not necessary and will has performance issues. We would like to implement an alternative.

     

    If we remove the unnecessary read in the success then we need some additional code to complete the synchronisation of client side data. We CANNOT send backup the current record in the same format as expected by the read, as this would require too many changes at the server end for us.

     

    For a CREATE we can change our server end code to return in the response the id value for the new record. For UPDATE and DESTROY can also change our server code to return in the response the id value of the original record. Please can you  provide alternative example code which uses the id value to complete synchronization in these cases.

  9. Stefan
    Admin
    Stefan avatar
    268 posts

    Posted 09 Nov Link to this post

    Hello Gary,

    My post was for the issue in this ticket.

    Apologies if my answer was not clear enough.

    From the described scenario I can confirm that based on the controller implementation, the Grid can work as expected if after every create, update or destroy the read method is called again (it is not very efficient approach but as the controller, implementation cannot be changed it is acceptable).

    The suggested approach in my previous post address the issue that because of the synchronise Ajax the read method is not successfully called after every create, update and destroy. That is why I suggest to not call it in the success function, but instead to use the requestEnd event of the DataSource to call the read method. 

    If this approach does not resolve the issue, please send a runnable example so we can investigate further and provide a suggestion best suited for it.

    Regards,
    Stefan
    Telerik by Progress
     
    Build rich, delightful, *native* Angular 2 apps with Kendo UI for Angular 2. Try it out today! Kendo UI for Angular 2 (currently in beta) is a jQuery-free toolset, written in TypeScript, designed from the ground up to offer true, native Angular 2 components.
     
  10. Gary
    Gary avatar
    9 posts
    Member since:
    Sep 2016

    Posted 09 Nov in reply to Stefan Link to this post

    Stefan,

    I am not sure if something is being lost in translation.

    What I have in place at the moment is working with a reread in the success. I do NOT want to have a reread anywhere after the response whether that be in the success function or requestEnd - this is a clumsy inefficient way of getting the client fully in sync.

    If we additionally pass back the record ID in the response is there a way to complete the sychronisation? The record already exists on the client so can I use this and the record ID to manually complete the synchronization?

     

    regards,

    Gary

  11. Stefan
    Admin
    Stefan avatar
    268 posts

    Posted 11 Nov Link to this post

    Hello Gary,

    After additional investigation and testing, I can suggest instead of calling the read method, to call options.success and pass the option.data as a parameter. This will ensure that the data will be in sync. Please have in mind that on create, you have to manually add the returned ID from the server to the options.data object:

    success: function (response) {
     options.success(options.data);
     //addressesDataSource.read();
    }

    I hope this approach will help to keep the data in sync and to remove the unnecessary read method.  

    Regards,
    Stefan
    Telerik by Progress
     
    Build rich, delightful, *native* Angular 2 apps with Kendo UI for Angular 2. Try it out today! Kendo UI for Angular 2 (currently in beta) is a jQuery-free toolset, written in TypeScript, designed from the ground up to offer true, native Angular 2 components.
     
  12. Gary
    Gary avatar
    9 posts
    Member since:
    Sep 2016

    Posted 17 Nov in reply to Stefan Link to this post

    Stefan,

    Thanks for your perseverance with this issue. In the end we have gone with the standard approach. We have managed to change our server side code without too many changes. We are now returning updated data to the client:

    success: function (result) {
        var JSONresult = JSON.parse(result);
         options.success(JSONresult.models);
    }

     

    A point to note and this seems to born out by other posts I have seen: there does not seem to be anywhere on www.telerik.com documenting the implementation requirements  for CUD operations to be synched properly i.e. data is returned to the client in the same format as expected by the read operation that is then passed to options.success()  in the success function.

     

    regards,

     

    Gary

  13. Answer
    Stefan
    Admin
    Stefan avatar
    268 posts

    Posted 21 Nov Link to this post

    Hello Gary,

    I'm glad to hear that the issue is resolved.

    Regarding the feedback for our documentation: We do have examples showing that the data should be passed to the success function when a Local data or a custom transport are used:

    http://docs.telerik.com/kendo-ui/framework/datasource/crud#local-or-custom-transport-crud-operations

    If you have a suggestion how to optimise the article, your feedback is greatly appreciated.

    Regards,
    Stefan
    Telerik by Progress
    Kendo UI is ready for Visual Studio 2017 RC! Learn more.
Back to Top
Kendo UI is VS 2017 Ready