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

Kendo Grid Custom Editor for Foreign Key Field...

9 Answers 676 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Robin
Top achievements
Rank 1
Robin asked on 11 Jul 2012, 08:50 PM
I have a table that has a foreign key to another table, and I would like to provide a dropdownlist as the editor for the foreign key field and then save the object back to the database using oData.
I can get the grid to create just fine, and CRUD operations work great on the main set of data.  
This leaves with me a couple of options.
I can simply bind the column to the foreign key field int field, and use a custom editor to create the dropdownlist to provide the id from the lookup table on, but leaves me displaying a simple int in the grid instead of a more meaningfull property of the lookup table.
Or I can use the $expand in the Read of the DataSource, include a field bound to the more meaningfull property, but can't get the editor to work quite right or the Update postback to work.

I have made some fiddles to try to show my point.
http://jsfiddle.net/giltnerj0/h4wx5/ 
http://jsfiddle.net/giltnerj0/h4wx5/1/ 
(These won't work for actual CRUD operations due to the JSONP from using demos.kendoui.com as the service)

9 Answers, 1 is accepted

Sort by
0
Rosen
Telerik team
answered on 12 Jul 2012, 07:25 AM
Hi Robin,

You should bind the editor to the whole Supplier object and use a template to display the CompanyName. Here is a modified version of one of the jsFiddles you have provided.

All the best,
Rosen
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Robin
Top achievements
Rank 1
answered on 12 Jul 2012, 01:19 PM
Thank you for the reply, that works great.  I am still having an issue with the actual PUT (Update) and POST (Create) service calls.  I get an error 400, Response body has message "Error processing request stream. Binding to new entities is not supported in PUT operations."  The Request body looks to be including the entire Supplier object when it sends the Product instead of just including SupplierID : 4 etc.

If I go back to showing the int value of SupplierID and not expanding the Supplier on READ, PUT and POSTS work as expected.

The oData CRUD operations sample you put on Github works great (https://github.com/telerik/kendo-examples-asp-net/blob/master/grid-odata-crud/Northwind.svc.cs), I just keep running into issues when I start expanding the odata calls to include child records.

0
Rosen
Telerik team
answered on 13 Jul 2012, 06:59 AM
Hello Robin,

Unfortunately, as far as I'm aware, oData does not support updating related entities through single request. Therefore, you may need to use a custom parameterMap to alter the format  of the changed data a bit.
Similar to the following:

parameterMap: function(options, type) {
    if (type !== "read") {
        options.SupplierID = options.Supplier.SupplierID;
        delete options.Supplier;
    }
    return kendo.data.transports["odata"].parameterMap(options, type);
}

Regards,
Rosen
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Robin
Top achievements
Rank 1
answered on 16 Jul 2012, 06:30 PM
Thank you. That works perfectly.
0
Ambica
Top achievements
Rank 1
answered on 25 Jul 2012, 03:02 PM
Hi Rosen,

I have checked this link  "http://jsfiddle.net/h4wx5/3/" for adding new row with foreign key relation. its working fine for other fields but not for Supplier field its updating Undefined. Please help me out

Thanks in advance

0
Robin
Top achievements
Rank 1
answered on 25 Jul 2012, 06:38 PM
Ambica,
I had to take care of that in my Parameter Map on the dataSource.

parameterMap: function(options, type) {
if(type == "update') {
options.supplier_id = options.Supplier.id;
delete options.Supplier;
}
else if(type == "create") {
options.supplier_id = options.Supplier;
delete options.Supplier;
}
return kendo.data.transports["odata"].parameterMap(options, type);
}

For some reason, when creating a new record, the id for the foreign key was stored as the Object, but when updating, it was stored properly as the Object.id.  Hope this makes sense.  You should be able to put a stop in the parameterMap function, and inspect the options object.
0
Ambica
Top achievements
Rank 1
answered on 27 Jul 2012, 11:31 AM
Hi Robin,
Thank you for replay.

I have tried with ParameterMap,its not working (Grid itself not binding, without Parameter Map its binding) 
I have debugged , when type=read, options object contains  as below.
  1. $expand"ProductGroup"
  2. groupArray[0]
  3. __proto__Object

is I am missing any thing ? below is my Code :

    _ProductDS = new kendo.data.DataSource({
        type: "odata",
        transport: {
            read: {             
                dataType: 'json',
            data: {
                $expand: "ProductGroup"
                   }                
            },
            create: {
                url: _WebServiceAddress + "dataapi/FieldForceProductGroups",
                contentType: 'application/json;odata=verbose',                
                complete: function (jqXHR, textStatus) {               
                    if (textStatus == "success") {                         
                        DisplayStatusMessage(_UpdatedSuccessful, StatusType.Confirmation, true);
                    }
                }
            },
            update: {
                url: function (data) {
                    return _WebServiceAddress + "dataapi/FieldForceProductGroups(guid'" + data.Id + "')";
                },
                contentType: 'application/json;odata=verbose',                
                complete: function (jqXHR, textStatus) {                    
                    if (textStatus == "success") {
                        DisplayStatusMessage(_UpdatedSuccessful, StatusType.Confirmation, true);
                    }
                }
            },
            destroy: {
                url: function (data) {
                    return _WebServiceAddress + "dataapi/FieldForceProductGroups(guid'" + data.Id + "')";
                },
                contentType: 'application/json;odata=verbose',                
                complete: function (jqXHR, textStatus) {                     
                    if (textStatus == "success") {                        
                        DisplayStatusMessage(_UpdatedSuccessful, StatusType.Confirmation, true);
                    }
                }
            } 
            parameterMap: function (options, type) {
                if (type == "update") {
                    options.ProductGroupId = options.ProductGroup.Id;
                    delete options.ProductGroup;
                }
                else if (type == "create") {                   
                    options.ProductGroupId = options.ProductGroupId;
                    delete options.ProductGroup;
                }
                return kendo.data.transports["odata"].parameterMap(options, type);
            }
            },         schema: {             total: function (data) {                 if (data != null || data.length > 0)                     return data.totalCount;                 else                     return 1;             },             data: function (data) {                 if (data.d != null) {                     return data.d.results;                 }             },             model: {                 id: "Id",                 fields: {                     Id: { editable: false, nullable: false },                                       Priority:{editable: true,  type: "number", validation: { required: true, min: 1}   },                 CreatedDateTime: { editable: true, type: "date", nullable: false, defaultValue: new Date() },                 ProductGroupId:{ editable: true},                     ProductGroup: {}                 }             }         } });

// Bind Grid

$("#divProduct").kendoGrid({
        autobind: false,
        scrollable: { virtual: true },
        height: 333,
        serverSorting: false,
        pageSize: 10,
        dataSource: _ProductDS,      
        toolbar: ["create"],
        columns: [          
        {
        field: "Priority",
        title: "Priority"
	}, 
         {
             field: "Name",
             width: "150px",
             template: "#=ProductGroup.Name#",           
             editor: ProductGroupDropDownEditor
         },   
       {command: ["edit", "destroy"] }
        ],
    editable: "inline"    
});

  function ProductGroupDropDownEditor(container, options)
  {
   $('<input data-text-field="Name" data-value-field="Id" data-bind="value:' + options.field + '"/>"')
 
                        .appendTo(container)
                        .kendoDropDownList({
                            autoBind: false,
                            dataSource: {
                                type: "odata",  
                                   transport: {
                                            read: {
                                                url: _WebServiceAddress + "dataapi/ProductGroups",
                                                dataType: 'json'
                                            }
                                        }
                                      }
                        });

  }
    
Please do me a need full.

Thank you
0
Robin
Top achievements
Rank 1
answered on 30 Jul 2012, 01:05 PM
Maybe I am just not seeing it, but I can't find where you are setting the URL for the read command in your datasource.
0
Ambica
Top achievements
Rank 1
answered on 30 Jul 2012, 01:41 PM
Hi Robin,

I have a Listview, which shows all field Force (Sales Rep details) , On selection of list view item , am binding grid by passing selected Field Force (Sales rep) ID. as  below.

ListView Binding
   $("#divFieldForceListView").kendoListView({  
       template: "<div id=${Id} style='width:100%;height:24px;cursor:pointer'><span style='padding-left:9px;line-height:24px;'>${Name} </span></div>"
   pageable: true,    
      selectable: true,    
      autoBind: false,     
     dataSource: _FieldForceListDS,     
     columns: ["Id""Name"],     
     change: OnFieldForceSelected  
   });

function
 OnFieldForceSelected(e) {
 ReadDataSource(e.sender.dataSource.view()[e.sender.select().index()].Id); 
...
}
//--------------------------------------------------------------------------------------------- 
// Change Dynamically Datasource to get data from the roster having id of pGUID
//---------------------------------------------------------------------------------------------
function ReadDataSource(pGuid) {  
    _FieldForceDetailsDS.transport.options.read.url = _WebServiceAddress + "dataapi/FieldForces?$filter=Id eq guid'" + pGuid + "'";
    _FieldForceDetailsDS.read();
}
Tags
Grid
Asked by
Robin
Top achievements
Rank 1
Answers by
Rosen
Telerik team
Robin
Top achievements
Rank 1
Ambica
Top achievements
Rank 1
Share this question
or