This only happens to the first column: Benefit
Any suggestions would be appreciated.
Here is my UI code:
@(Html.Kendo().Grid<OtherBenefitMappingModel>() .Name("OtherBenefitMappingByUserGrid") .Columns(columns => { columns.Bound(p => p.OtherBenefitMappingId).Hidden(true); columns.ForeignKey(b => b.BenefitRecordId, Model.OtherBenefitMappingsByUser, "BenefitRecordId", "BenefitDescriptionText").EditorTemplateName("BenefitDescriptionDropDown").Title("Benefit").Filterable(false); columns.ForeignKey(b => b.AppendixD1ElementId, Model.AppendixD1ElementModels, "AppendixD1ElementId", "AppendixD1ElementName").EditorTemplateName("AppendixD1DropDown").Title("Appendix").Filterable(false); columns.Bound(p => p.MappedBy).Title("Mapped By"); columns.Bound(p => p.LastModifiedDate).Title("Mapped Date").Format("{0:MM/dd/yyyy}"); columns.Command(command => { command.Edit(); command.Destroy(); }).Width(175); }) .Pageable() .Sortable() .ToolBar(toolbar => toolbar.Create()) .Editable(editable => editable.Mode(GridEditMode.InLine)) .DataSource(dataSource => dataSource .Ajax() .Create(create => create.Action("OtherBenefitMappingsByUserGridCreator", "EHBReview")) .Read(read => read.Action("OtherBenefitMappingsByUserGridReader", "EHBReview")) .Update(update => update.Action("OtherBenefitMappingsByUserGridUpdater", "EHBReview")) .Destroy(delete => delete.Action("AjaxPrimaryOtherMappingGridRowDeleter", "EHBReview")) .Model(model => { model.Id(p => p.OtherBenefitMappingId); model.Field(a => a.LastModifiedDate).Editable(false); model.Field(a => a.MappedBy).Editable(false); }) ) )
@
using
System.Collections
@
using
Kendo.Mvc.UI
@(Html.Kendo().DropDownList()
.Name(
"BenefitRecordId"
)
.DataTextField(
"BenefitDescriptionText"
)
.DataValueField(
"BenefitRecordId"
)
.SelectedIndex(-1)
.OptionLabel(
"Select..."
)
.BindTo((IEnumerable) ViewData[
"OtherBenefitDescriptionData"
])
)
public ActionResult OtherBenefitMapping(int productId)
{
if (productId < 1)
{
return NoData();
}
Session["ProductId"] = productId;
return View(LoadOtherBenfitMappingPageModel(productId));
}
private OtherBenefitMappingPageModel LoadOtherBenfitMappingPageModel(int productId)
{
IEnumerable<vOtherBenefitMap> vOtherBenefitMaps = _otherBenefitMappingDataProvider.GetByProductId(productId).ToList();
var model = new OtherBenefitMappingPageModel
{
OtherBenefitMappingsBySystem = vOtherBenefitMaps.Where(a => a.MappedBy == "system").Select(e => new OtherBenefitMappingModel(e)).ToList(),
BenefitRecordsNotMappedBySystem = vOtherBenefitMaps.Where(a => a.MappedBy != "system").Select(e => new BenefitRecordModel(e)).Distinct().ToList(),
OtherBenefitMappingsByUser = vOtherBenefitMaps.Where(a => a.MappedBy != "system" && a.OtherBenefitMappingId > 0).Select(e => new OtherBenefitMappingModel(e)).ToList(),
AppendixD1ElementModels = _appendixD1ElementDataProvider.GetAll().Select(e => new AppendixD1ElementModel(e)).OrderBy(e => e.AppendixD1ElementName).ToList(),
};
ViewData["OtherBenefitDescriptionData"] = model.BenefitRecordsNotMappedBySystem;
ViewData["AppendixD1Data"] = model.AppendixD1ElementModels;
return model;
}
public JsonResult OtherBenefitMappingsByUserGridCreator([DataSourceRequest] DataSourceRequest request, OtherBenefitMapping obm) { var result = new List<OtherBenefitMappingModel>(); if (!ModelState.IsValid || obm == null) { return null; } obm.ProductId = (int) Session["ProductId"]; obm.MappedBy = User.Identity.Name; obm.LastModifiedDate = DateTime.Now; OtherBenefitMapping otherBenefitMapping = _otherBenefitMappingDataProvider.Create(obm); result.Add(new OtherBenefitMappingModel(otherBenefitMapping)); return Json(result.ToDataSourceResult(request), JsonRequestBehavior.AllowGet); } public JsonResult OtherBenefitMappingsByUserGridReader([DataSourceRequest] DataSourceRequest request) { DataSourceResult result = GetOtherBenefitMappingsByUser().ToDataSourceResult(request); return Json(result, JsonRequestBehavior.AllowGet); } private IEnumerable<OtherBenefitMappingModel> GetOtherBenefitMappingsByUser() { int productId = (int)Session["ProductId"]; var model = LoadOtherBenfitMappingPageModel(productId); return model.OtherBenefitMappingsByUser; } public JsonResult OtherBenefitMappingsByUserGridUpdater([DataSourceRequest] DataSourceRequest request, OtherBenefitMapping obm) { if (!ModelState.IsValid || obm == null) { return null; } OtherBenefitMapping otherBenefitMapping = _otherBenefitMappingDataProvider.Get(obm.OtherBenefitMappingId); otherBenefitMapping.AppendixD1ElementId = obm.AppendixD1ElementId; otherBenefitMapping.BenefitRecordId = obm.BenefitRecordId; _otherBenefitMappingDataProvider.Update(otherBenefitMapping); var result = new List<OtherBenefitMappingModel> {new OtherBenefitMappingModel(otherBenefitMapping)}; return Json(result.ToDataSourceResult(request), JsonRequestBehavior.AllowGet); } public JsonResult AjaxPrimaryOtherMappingGridRowDeleter([DataSourceRequest] DataSourceRequest request, OtherBenefitMapping obm) { if (!ModelState.IsValid || obm == null) { return null; } OtherBenefitMapping otherBenefitMapping = _otherBenefitMappingDataProvider.Get(obm.OtherBenefitMappingId); _otherBenefitMappingDataProvider.Delete(otherBenefitMapping); return Json(null, JsonRequestBehavior.AllowGet); }
22 Answers, 1 is accepted
From the code it seems that you are overriding the editor templates for both foreign key columns. Have you created an editor template named "AppendixD1DropDown"? If no, you can remove the EditorTemplateName method and since there is a "GridForeignKey" template it will automatically be picked. If there is a "AppendixD1DropDown" template, I will need a small test project so I can investigate what exactly goes wrong.
Regards,Daniel
the Telerik team

my code is the following:
"My partialView"
@(Html.Kendo().Grid<namespace.Models.ModelClassName>()
.Name("Grid")
.Columns(columns =>
{
columns.Bound(p => p.isActionDesc).Title("title");
columns.ForeignKey(p => p.isStatusID, (System.Collections.IEnumerable)ViewData["actionstatuses"], "isID", "isDesc").Title("title");
columns.Bound(p => p.isStartDate).Title("title").Format("{0:dd/MM/yyyy hh:mm:ss}");
columns.Bound(p => p.isEndDate).Title("title").Format("{0:dd/MM/yyyy hh:mm:ss}"); ;
columns.Bound(p => p.isDuration).Title("title");
columns.Bound(p => p.isComments).Title("title");
columns.Bound(p => p.isResult).Title("title");
columns.Command(command => { command.Edit(); command.Destroy(); }).Width(50);
})
.Pageable()
.ColumnMenu()
.Filterable()
.Sortable()
.Selectable()
.ToolBar(toolbar => toolbar.Create())
.Editable(editable => editable.Mode(GridEditMode.InLine))
.DataSource(dataSource => dataSource
.Ajax() // Specify that the data source is of ajax type
.Model(model => model.Id(p => p.isID) )
.Create(update => update.Action("EditingInline_Create", "IsAction"))
.Read(read => read.Action("EditingInline_Read", "IsAction"))
.Update(update => update.Action("EditingInline_Update", "IsAction"))
.Destroy(update => update.Action("EditingInline_Destroy", "IsAction"))
//.Read(read => read.Action("SActions_Read", "IsAction"))
)
)
And the Action is the following:
public class IsActionController : Controller{
.......
public ActionResult KendoSupportActions()
{
System.Diagnostics.Debug.Print("Kendo Grid");
ViewData["actionstatuses"] = db.ActionStatus;
return PartialView("KendoSupportActions");
}
The code looks correct. Nothing will be displayed in the cell if the value from the record cannot be matched with any of the values in the passed collection. Could you share some of the data you are using or a small test project so I can check if this is causing the problem?
Regards,Daniel
the Telerik team

I found this to be the case for both incell and inline editing when using both .ForeignKey but also when you use your own dropdownlist editor template as well.
public Nullable<
int
> CustomerId { get; set; }
public int CustomersId { get; set; }
columns.ForeignKey(l => l.CustomerId, (IEnumerable<
DDLOptions
<int>>)Model.CustomerOptions, "Value", "DisplayText").Width(300);
columns.ForeignKey(l => l.CustomersId, (IEnumerable<
DDLOptions
<int>>)Model.CustomerOptions, "Value", "DisplayText").Width(300);
This behavior is expected. When the value is null, the value binding returns the selected item and not the selected value. If the value can be null, you should bind the dropdown to an object as demonstrated in the custom editor demos.
Regards,Daniel
the Telerik team

I ended up posting a ticket for this and Vladimire confirmed this is not supported out of the box, but there is a work around. Here is his response for those of you following at home.
Hi Chad,
Thank you for contacting Telerik Support.
Currently the ForeignKeyColumn does not support nullable values out-of-the-box, however it's possible to achieve the desired behavior by using the Save event of the Grid to change the model value to zero, get currently selected value from the DropDownList and set it to the model - please check the example below:
function
onSave(e) {
//If current value is null
if
(!e.model.CustomerId) {
//change the model value
e.model.CustomerId= 0;
//get the currently selected value from the DDL
var
currentlySelectedValue = $(e.container.find(
'[data-role=dropdownlist]'
)[0]).data().kendoDropDownList.value();
//set the value to the model
e.model.set(
'CustomerId'
, currentlySelectedValue);
}
}
I hope this information helps. Wish you a great day. Kind Regards,
Vladimir Iliev
the Telerik team
There are no other known reasons for this behavior. If the value is initially null before entering edit mode than the binding will be to an object and not the selected value. If the value is not null in your scenario then this could be caused by another issue. Could you share a runnable project so I can investigate if that is the case?
As for the approach that my colleague Vladimir suggested updates the value manually and should work.
Daniel
the Telerik team

Unfortunately my project is quite large and it will take a while for me to create a separate runnable project. I tried to take the sample that Vladimir created and sent me as a base and just change the ProductId to a type Nullable<int> in the model...but that caused other errors that I could not figure out. If you take that sample project and change the ProductId to a Nullable<int>, then hopefully this will reproduce the issue for you.

I was able to create a runnable project that shows this problem.
The problem is as such: when you have a model property type of Nullable int (int?), the selected values of the kendo DDL are not updated to the model prior to submitting the model to the controller for create or update. Hence you need the code specified above to manually update the model values prior to sending the model to the controller.
To replicate:
- run the project attached with a breakpoint on the Create action of the controller
- on the grid, click Add
- Select Customer 1, Vendor 1, Product 1
- Click Update
- See breakpoint in controller. Note model has VendorId and Product ID as NULL instead of 1
The default values are null when the the field is Nullable and will be used when adding a new item. If the values can be null only when creating a new record, you can avoid binding to the selected item also by setting a different default value through the DataSource model e.g.
.DataSource(dataSource => dataSource
.Ajax()
.Model(model =>
{
model.Id(p => p.LicenseId);
model.Field(p => p.ProductId).DefaultValue(0);
model.Field(p => p.VendorId).DefaultValue(0);
})
Regards,
Daniel
the Telerik team


I think I am confused by the reference to default values, as the issue I am trying to explain is that when you create a new row in the grid, but then select a value in the dropdownlist, then save the row, shouldn't the value just selected in the list be populated in the model and passed back to the controller?
It is not. It is passing null to the controller, even though you selected a value in the dropdownlist. This behaviour can be seen in the project I posted a link to above. I would not think that it would be expected behavior to selected a value in the dropdownlist, but have the model value still be null.
The default value is used for the new item and for nullable types it will default to null. Because when the initial value is null the value binding tries to update the field with the entire item from the dropdown not just the value, the field will not be updated correctly.
Regards,Daniel
the Telerik team

This problem is actually more generic. In another popup view, I have a grid. If I click a link in a row, and immediately mouse off the row, the javascript bound to the click event is fired, but does not get the row I just clicked using something like myGrid.select()[0]. It still sees the previously selected row as the row as the currently selected row; not the one I just clicked in. I changed this click event to receive the uid of the row, so I am able to pass back the correct identifier of the row, and then iterate to find the row I wanted.
To further define the problem related to the foreignkey, I've declared the Change event at the grid level (not datasource). This event fires if I click the row without moving the mouse. But if I click in the row and then immediately mouse out, the event does not fire, but the template is still loaded.

I have a field like this:
{ width: 70, field: "Tier", editor: tierDropDownEditor},
And my tierDropDownEditor dynamically populates the available options from another field of the model:How do I get the selected value to appear when the editbox is not active?function tierDropDownEditor(container, options) {
var avail = options.model.AvailablePricingTiers;
var primaryProduct = options.model.PrimaryProductId;
var availablePricingTiersList = [];
for (var i = 0; i <
avail.length
; i++) {
if (primaryProduct == avail
[i].ProductId
) // If it is the same as the selected primary product, add it to the dropdown list
{
availablePricingTiersList.push({ Description: avail[i].Name, ID: avail[i].PricingTierId});
}
}
if (availablePricingTiersList.length > 0) {
$('<
input
data-text-field
=
"Description"
data-value-field
=
"ID"
data-bind
=
"value:' + options.field + '"
/>')
.appendTo(container)
.kendoComboBox({
dataSource: availablePricingTiersList,
dataTextField: "Description",
dataValueField: "ID",
});
}
};
I'd like to be able to do something like this, but this doesn't do it:{ width: 70, field: "Tier", editor: tierDropDownEditor, values: "AvailablePricingTiers"},

I don't really need the list of available values to come from the model. And I had a typo that was causing it to not work when I was getting it from elsewhere.

Just modify your Model:
01.
public
class
SomeModel
02.
{
03.
private
int
? _someFkId {
get
;
set
; }
04.
05.
[Display(Name =
"Fancy Name"
)]
06.
public
int
? SomeFkId
07.
{
08.
get
{
return
_someFkId ; }
09.
set
{ _someFkId = value; }
10.
}
11.
/// <summary>
12.
/// Use this one when mapping to Kendo Grid ForeignKey
13.
/// </summary>
14.
[Display(Name =
"Fancy Name"
)]
15.
public
string
SomeFkId_KendoFk
16.
{
17.
get
{
return
_someFkId.ToString(); }
18.
set
{
19.
int
id;
20.
if
(
int
.TryParse(value,
out
id))
21.
{
22.
_someFkId = id;
23.
return
;
24.
}
25.
_someFkId =
null
;
26.
}
27.
}
28.
etc...
29.
}
Then just map to the _KendoFk version of your property. LOL!
I laugh because this is so wrong in so many ways. But it works.
You also don't need an editor template or brittle client-side code.

Telerik MVC Scaffold code generator for ajax inline or inCell do not includes the foreign key fields in the controller code, review your controller code, add the missing fields and everything should be good.
Regards,

This is quite an old thread which seems to incorporate several challenges which our clients have encountered.
Could you specify what seems to be the issue which you are experiencing and give me some context of the Kendo UI Grid in your application? This way I can advise in accordance with your scenario and the current Kendo UI/ UI for ASP.NET MVC versions?
Kind Regards,
Alex Hajigeorgievathe Telerik team

What I don't understand is if I can set the option label and set the value primitive to true, why doesn't the option label display when the value is null? The dropdownlist is only visible if I click in the cell. Am I missing something here?
@(
Html.Kendo().DropDownListFor(m => m)
.BindTo((SelectList)ViewData[ViewData.TemplateInfo.GetFullHtmlFieldName("") + "_Data"])
.OptionLabel("Choose Option")
.ValuePrimitive(true)
)
@(Html.Kendo().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
columns.ForeignKey(fk => fk.WriteOffCounty, (System.Collections.IEnumerable)ViewData["CountyList"], "ID", "Description").Title("xWrite Off County");
columns.Bound(c => c.ClaimMasterID);
})
.ToolBar(tools => { tools.Excel(); })
.Pageable()
.Sortable()
.Filterable()
.Groupable()
.Editable(editable => editable.Mode(GridEditMode.InCell))
.Scrollable(scr => scr.Height(400))
.NoRecords("No results found")
.Reorderable(r => r.Columns(true))
.Resizable(r => r.Columns(true))
.Excel(excel => excel
.FileName("Grid.xlsx")
.AllPages(true)
.ProxyURL(Url.Action("Excel_Export_Save", "GridStuff"))
)
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(100)
.Read(read => read.Action("ReadGridStuff", "GridStuff"))
.Model(model =>
{
model.Id(m => m.ClaimMasterID);
model.Field(f => f.ClaimMasterID).Editable(false);
})
)

I figured it out. I used the clientTemplate. It will add default text to the cell. Once you click the cell the dropdownlist will display instead. I got the idea from the grid demo here: http://demos.telerik.com/aspnet-mvc/grid/editing-custom.
All I did was add the following: .ClientTemplate("Choose Option").
See Below.
columns.ForeignKey(fk => fk.WriteOffCounty, (System.Collections.IEnumerable)ViewData["CountyList"], "ID", "Description").Title("xWrite Off County").ClientTemplate("Choose Option");