Grid with Foreign Key Column Displaying Blank After Creation

19 posts, 0 answers
  1. Pouya
    Pouya avatar
    6 posts
    Member since:
    Mar 2011

    Posted 26 Nov 2012 Link to this post


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



  2. Daniel
    Admin
    Daniel avatar
    2117 posts

    Posted 29 Nov 2012 Link to this post

    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!
  3. Kendo UI is VS 2017 Ready
  4. Kostas
    Kostas avatar
    1 posts
    Member since:
    Nov 2012

    Posted 30 Nov 2012 Link to this post

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

            }
  5. Daniel
    Admin
    Daniel avatar
    2117 posts

    Posted 04 Dec 2012 Link to this post

    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!
  6. Chad
    Chad avatar
    29 posts
    Member since:
    Nov 2012

    Posted 19 Jan 2013 Link to this post

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


  7. Daniel
    Admin
    Daniel avatar
    2117 posts

    Posted 24 Jan 2013 Link to this post

    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!
  8. Chad
    Chad avatar
    29 posts
    Member since:
    Nov 2012

    Posted 24 Jan 2013 Link to this post

    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
  9. Daniel
    Admin
    Daniel avatar
    2117 posts

    Posted 29 Jan 2013 Link to this post

    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!
  10. Chad
    Chad avatar
    29 posts
    Member since:
    Nov 2012

    Posted 29 Jan 2013 Link to this post

    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.
  11. Chad
    Chad avatar
    29 posts
    Member since:
    Nov 2012

    Posted 31 Jan 2013 Link to this post

    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)
  12. Daniel
    Admin
    Daniel avatar
    2117 posts

    Posted 01 Feb 2013 Link to this post

    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!
  13. Hatton Point
    Hatton Point avatar
    14 posts
    Member since:
    Dec 2012

    Posted 01 Feb 2013 Link to this post

    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.


  14. Chad
    Chad avatar
    29 posts
    Member since:
    Nov 2012

    Posted 13 Feb 2013 Link to this post

    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.
  15. Daniel
    Admin
    Daniel avatar
    2117 posts

    Posted 18 Feb 2013 Link to this post

    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!
  16. cracka!
    cracka! avatar
    3 posts
    Member since:
    Oct 2012

    Posted 22 Feb 2013 Link to this post

    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.
  17. Craig
    Craig avatar
    12 posts
    Member since:
    Feb 2013

    Posted 11 Mar 2013 Link to this post

    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"},
  18. Craig
    Craig avatar
    12 posts
    Member since:
    Feb 2013

    Posted 11 Mar 2013 Link to this post

    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.
  19. Trey
    Trey avatar
    1 posts
    Member since:
    Jan 2012

    Posted 10 Sep 2013 Link to this post

    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.
  20. Mauricio
    Mauricio avatar
    -1 posts
    Member since:
    Aug 2015

    Posted 20 Aug Link to this post

    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,

Back to Top
Kendo UI is VS 2017 Ready