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

Grid with Foreign Key Column Displaying Blank After Creation

22 Answers 1363 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Pouya
Top achievements
Rank 1
Pouya asked on 26 Nov 2012, 06:03 PM


I am aware of the EditorTemplate required file (GridForeignKey.cshtml) and it is where it is supposed to be.
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.BenefitRecordIdModel.OtherBenefitMappingsByUser"BenefitRecordId""BenefitDescriptionText").EditorTemplateName("BenefitDescriptionDropDown").Title("Benefit").Filterable(false);
		columns.ForeignKey(b => b.AppendixD1ElementIdModel.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);
											})
)
)		
Here is my editor template:
@using System.Collections
@using Kendo.Mvc.UI
             
 
@(Html.Kendo().DropDownList()
        .Name("BenefitRecordId")
        .DataTextField("BenefitDescriptionText")
        .DataValueField("BenefitRecordId")
        .SelectedIndex(-1)
        .OptionLabel("Select...")
        .BindTo((IEnumerable) ViewData["OtherBenefitDescriptionData"])
    )
            
Here is the corresponding code for the view:
		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([DataSourceRequestDataSourceRequest request, OtherBenefitMapping obm)
		{
			var result = new List<OtherBenefitMappingModel>();
			if (!ModelState.IsValid || obm == null)
			{
				return null;
			}
			obm.ProductId = (intSession["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([DataSourceRequestDataSourceRequest request)
		{
			DataSourceResult result = GetOtherBenefitMappingsByUser().ToDataSourceResult(request);
			return Json(result, JsonRequestBehavior.AllowGet);
		}
 
		private IEnumerable<OtherBenefitMappingModelGetOtherBenefitMappingsByUser()
		{
			int productId = (int)Session["ProductId"];
			var model = LoadOtherBenfitMappingPageModel(productId);
			return model.OtherBenefitMappingsByUser;
		}
 
		public JsonResult OtherBenefitMappingsByUserGridUpdater([DataSourceRequestDataSourceRequest 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([DataSourceRequestDataSourceRequest request, OtherBenefitMapping obm)
		{
			if (!ModelState.IsValid || obm == null)
			{
				return null;
			}
			OtherBenefitMapping otherBenefitMapping = _otherBenefitMappingDataProvider.Get(obm.OtherBenefitMappingId);
			_otherBenefitMappingDataProvider.Delete(otherBenefitMapping);
			return Json(nullJsonRequestBehavior.AllowGet);
		}



22 Answers, 1 is accepted

Sort by
0
Daniel
Telerik team
answered on 29 Nov 2012, 03:42 PM
Hi,

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
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Kostas
Top achievements
Rank 1
answered on 30 Nov 2012, 08:46 AM
I am facing a similar problem. The column is not displaying the item's value when it is in normal view state. When i click the edit button then I can see the dropdownlist populated just fine. I have a blanc cell only when I am in view mode. I am not using a custom editor template, I use the GridForeignKey template provided with kendo asp.net mvc.
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");

        }
0
Daniel
Telerik team
answered on 04 Dec 2012, 07:54 PM
Hello Kostas,

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
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Chad
Top achievements
Rank 1
answered on 19 Jan 2013, 05:41 PM
I am having the same issue and it seems to be related to only where properties are defined as a nullable int. If I take the exact some property in my view model that is nullable int and copy it and make it a plain in, the plain int one acts as expected, but the nullable int does not. You can select the value in the dropdownlist ok but as soon as the cell or row in the grid goes from edit mode to view mode, those grid cells are blank.

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);


0
Daniel
Telerik team
answered on 24 Jan 2013, 07:01 AM
Hello Chad,

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
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Chad
Top achievements
Rank 1
answered on 24 Jan 2013, 04:07 PM
Hello Daniel and thanks for the reply, but I don't quite understand what you are saying and not sure I was clear either. In my case, the value in the model is not null. It has some value....but in cases where that model property is of type int?, even though the value is NOT null, the correct DisplayText is not shown while in view mode.

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
0
Daniel
Telerik team
answered on 29 Jan 2013, 01:23 PM
Hello again Chad,

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. 

Regards,
Daniel
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Chad
Top achievements
Rank 1
answered on 29 Jan 2013, 03:19 PM
Thanks Daniel for the reply. The value is not null in my model so there must be something else going on. 
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.
0
Chad
Top achievements
Rank 1
answered on 31 Jan 2013, 09:49 PM
Daniel,

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:
  1. run the project attached with a breakpoint on the Create action of the controller
  2. on the grid, click Add
  3. Select Customer 1, Vendor 1, Product 1
  4. Click Update
  5. See breakpoint in controller. Note model has VendorId and Product ID as NULL instead of 1
Here is a link to the project (could not upload due to 2MB limit)
0
Daniel
Telerik team
answered on 01 Feb 2013, 06:53 AM
Hello Chad,

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);
              })
Otherwise, you should either bind the dropdownlists to objects or use the approach that Vladimir suggested and update the values with custom code.

Regards,
Daniel
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Hatton Point
Top achievements
Rank 1
answered on 01 Feb 2013, 09:38 AM
Had the same issue. I am passing in nullable and non-nullable int. When the type is null, it does show up as expected in both the edit and view modes, but it would not let me save a selection. The javascript onSave workaround helped me. If there is a better, more examples solution I would look into it, but for now the javascript works.


0
Chad
Top achievements
Rank 1
answered on 14 Feb 2013, 03:53 AM
Hello Daniel,

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.
0
Daniel
Telerik team
answered on 18 Feb 2013, 02:25 PM
Hello Chad,

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
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
cracka!
Top achievements
Rank 1
answered on 22 Feb 2013, 02:04 PM
I have an interesting twist to the foreignkey problem.  If I click on the grid row, and immediately mouse off the row, the row I just clicked is not selected, but the template is displayed in that cell.  My problem is that I need to change what is displayed in the template based on whether the row is new or not.  In my template, I try to get the selected cell data to display as text in the template.  Otherwise, I show a drop down list for displaying a list of possible items to select.  In this case, the selected row is not the same as where the template is displayed, and I end up showing an empty string in the partial view that is the template in the cell.

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.
0
Craig
Top achievements
Rank 1
answered on 11 Mar 2013, 07:23 PM
I'm basically having the same issue and having trouble figuring out how to fix it without using MVC helpers.

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:
 
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",
            });
    }
};
How do I get the selected value to appear when the editbox is not active?
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"},
0
Craig
Top achievements
Rank 1
answered on 11 Mar 2013, 07:56 PM
Never mind - I figured out what I was doing wrong here.
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.
0
Trey
Top achievements
Rank 1
answered on 10 Sep 2013, 10:16 PM
Here is an alternate workaround.  Though you will laugh at our desperation to go to this length...
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.
0
Mauricio
Top achievements
Rank 1
answered on 21 Aug 2016, 01:16 AM

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,

0
Thomas
Top achievements
Rank 1
answered on 21 Jun 2017, 08:31 PM
Thanks for this solution Trey. It is quit odd that such a normal action needs a solution like this. Really dirty, like u mentioned. It's a bit of a shame that this issue still isn't fixed (or even acknowledged) by the Telerik team. I still hope they can make this work for int? just as easy as it does for int...
0
Alex Hajigeorgieva
Telerik team
answered on 26 Jun 2017, 03:50 PM
Hello Thomas,

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 Hajigeorgieva
the Telerik team
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Kevin
Top achievements
Rank 1
answered on 07 Sep 2017, 08:36 PM

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);
                        })
            )

0
Kevin
Top achievements
Rank 1
answered on 07 Sep 2017, 08:58 PM

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");

Tags
Grid
Asked by
Pouya
Top achievements
Rank 1
Answers by
Daniel
Telerik team
Kostas
Top achievements
Rank 1
Chad
Top achievements
Rank 1
Hatton Point
Top achievements
Rank 1
cracka!
Top achievements
Rank 1
Craig
Top achievements
Rank 1
Trey
Top achievements
Rank 1
Mauricio
Top achievements
Rank 1
Thomas
Top achievements
Rank 1
Alex Hajigeorgieva
Telerik team
Kevin
Top achievements
Rank 1
Share this question
or