This is a migrated thread and some comments may be shown as answers.

[Solved] grid with custom editor add new record and post to odata

6 Answers 176 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Wit
Top achievements
Rank 1
Wit asked on 14 Oct 2014, 07:56 PM
hi,
it is a follow up to: link

I have a grid with custom editor:

{ field: "Application", title: "Owned By", width: "120px", editor: applicationDropDownEditor, template: "#=Application.ApplicationName#" }

editor:
var applicationDataSource = {
                type: "odata",
                transport: {
                    read: {
                        url: "odata/Sys_Application",
                        dataType: "json",
                        type: "GET"
                    },
                },
                schema: {
                    data: "value",
                    total: "count"
                },
            }
 
            function applicationDropDownEditor(container, options) {
                $('<input required data-bind="value:' + options.field + '"/>')
                    .appendTo(container)
                    .kendoDropDownList({
                        autoBind: false,
                        dataTextField: "ApplicationName",
                        dataValueField: "ApplicationRef",
                        dataSource: applicationDataSource
 
                    });
            }


I am trying to add a new record. So I click add new enter values select value form drop down. That is when I encounter my first problem - I can't select first value - I can select it but is not recognised as selection and when cell looses focus I am loosing value.

Than I press Save and data is sent to odata controller

// POST: odata/Entities
        public async Task<IHttpActionResult> Post(Entity entity)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
 
            db.Entry(entity.Application).State = EntityState.Unchanged;
 
            db.Entities.Add(entity);
            await db.SaveChangesAsync();
 
            return Created(entity);
        }

Here I am saving record to db. Following this article  I had to mark drop down data as unchanged to make sure EF will not try to reinsert values. Then I am sending created entity back to client.

As I am using web api odbc v3 I had to make some changes to schema, data value

schema: {
                       data: function (data) {
                           if (data.value) {
                               return data.value;
                           }
                           delete data["odata.metadata"];
                           return [data];
                       }

And that is when my second problem starts - returned data has no Application property and that is what my field template is expecting - I have only ApplicationRef which is a foreign key.

How can I make sure that my new row will display a correct value in  drop down list when new record is saved and made a round trip to server and back?

Please find sample project: here

6 Answers, 1 is accepted

Sort by
0
Daniel
Telerik team
answered on 17 Oct 2014, 08:17 AM
Hello Wit,

The first problem will occur because currently the change event will not be triggered when the set value does not match the value field of the items and it automatically selects the first item. In order to avoid the problem I can suggest to use an option label and required validation or trigger the change event in the dataBound event:
function applicationDropDownEditor(container, options) {
    var dropdownlist = $('<input required data-bind="value:' + options.field + '"/>')
        .appendTo(container)
        .kendoDropDownList({
            autoBind: false,
            dataTextField: "ApplicationName",
            dataValueField: "ApplicationRef",
            dataSource: applicationDataSource
        }).data("kendoDropDownList");
    dropdownlist.one("dataBound", function () {
        dropdownlist.trigger("change");
    });
}

As for the other problem - I am not sure if it is possible to expand the entity on POST. At least I couldn't make it work. If it is not possible then I can suggest to reassign the object in the requestEnd event:
requestEnd: function (e) {
    if (e.type == "create") {
        var response = e.response;
        var application = this.data().find(function (item) {
            return item.isNew();
        }).Application;                           
        response.Application = application.toJSON();
    }
}


Regards,
Daniel
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Wit
Top achievements
Rank 1
answered on 17 Oct 2014, 08:54 AM
Hi Daniel,

Could you please explain what is that bit of code doing ?

var application = this.data().find(function (item) {
            return item.isNew();
        }).Application;                          
        response.Application = application.toJSON();
0
Wit
Top achievements
Rank 1
answered on 21 Oct 2014, 06:01 AM
Hi,

Your suggestion works for changes generated by user, is it possible to force drop down to change it's value based on foreign key passed from server?

if (e.type == "create") {
                           var response = e.response;
 
                           if (response.OwnedByRef) {
                               var ownedBy = this.data().find(function (item) {
                                   item.OwnedByRef = response.OwnedByRef;
                                   return item.isNew();
                               }).Application;
                               response.Application = ownedBy.toJSON();
                           }
 
                       }
0
Daniel
Telerik team
answered on 21 Oct 2014, 07:45 AM
Hello again Wit,

Yes, it is possible but you will need the applications data in this case. You could initialize a dataSource instance from the "applicationDataSource" options and then use the dataSource to find the correct application object e.g.
requestEnd: function (e) {
    if (e.type == "create") {
        var response = e.response;       
        var application = applicationDataSource.data().find(function (item) {
          return item.ApplicationRef === e.response.OwnedByRef
        });           
        response.Application = application.toJSON();
    }
},
var applicationDataSource = new kendo.data.DataSource({
    type: "odata",
    transport: {
        read: {
            url: "odata/Sys_Application",
            dataType: "json",
            type: "GET"
        },
    },
    schema: {
        data: "value",
        total: "count"
    }
});

As for the code from my previous reply - it finds the created item in the grid dataSource data and then sets the Application object to the response.

Regards,
Daniel
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Wit
Top achievements
Rank 1
answered on 21 Oct 2014, 08:42 AM
Should : applicationDataSource.data() get date as at the moment I am getting nothing out of it. It doesn't even sent request to server 

I have modified my code to match yours:

if (e.type == "create") {
                           var response = e.response;
 
                           if (response.OwnedByRef) {
                               var ownedBy = applicationDataSource.data().find(function (item) {
                                   return item.ApplicationRef === response.OwnedByRef;
                                   //return item.isNew();
                               });
                               response.Application = ownedBy.toJSON();
                           }
 
                       }
var applicationDataSource = new kendo.data.DataSource({
               type: "odata",
               transport: {
                   read: {
                       url: "odata/Sys_Application",
                       dataType: "json",
                       type: "GET"
                   },
               },
               schema: {
                   data: "value",
                   total: "count"
               },
           });
0
Accepted
Daniel
Telerik team
answered on 22 Oct 2014, 08:23 AM
Hello Wit,

No data will be returned from the data method if the dataSource has not been read by the dropdownlist. You could read the data after initialization in order for the data to be populated in this scenario:
var applicationDataSource = new kendo.data.DataSource({
   type: "odata",
   transport: {
       read: {
           url: "odata/Sys_Application",
           dataType: "json",
           type: "GET"
       },
   },
   schema: {
       data: "value",
       total: "count"
   }
});
 
applicationDataSource.read();


Regards,
Daniel
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
Tags
Grid
Asked by
Wit
Top achievements
Rank 1
Answers by
Daniel
Telerik team
Wit
Top achievements
Rank 1
Share this question
or