Model property not set when bound to object

15 posts, 0 answers
  1. Bill Wingate
    Bill Wingate avatar
    12 posts
    Member since:
    Feb 2009

    Posted 02 Mar Link to this post

    I have these model classes:

    public class Part
    {
        public Guid Id { get; set; }
        string Name { get; set; }
        public Part()
        {
        }
    }
     
    public class DetailItem
    {
        public Guid Id { get; set; }
        public Part Part { get; set; }
     
        public DetailItem()
        {
        }
    }

    In my View, the model is the DetailItem. I am trying to use a ComboBox to select the Part for the DetailItem:

     

    @(Html.Kendo().ComboBoxFor(model => model.Part)
        .DataValueField("Id")
        .DataTextField("Name")
        .Filter(FilterType.Contains)
        .DataSource(source =>
        {
            source.Read(read =>
            {
                read.Action("GetParts", "RefData");
            })
     
            .ServerFiltering(true);
        }
        )
    )

    When I save the page, the DetailItem.Part never gets set from the ComboBox. How do I make this work?
  2. Daniel
    Admin
    Daniel avatar
    2118 posts

    Posted 07 Mar Link to this post

    Hello,

    Is the combobox posted with a form? If yes, then you should bind the combobox to the Part.Id property:
    Html.Kendo().ComboBoxFor(model => model.Part.Id)


    Regards,
    Daniel
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  3. UI for ASP.NET MVC is VS 2017 Ready
  4. Bill Wingate
    Bill Wingate avatar
    12 posts
    Member since:
    Feb 2009

    Posted 07 Mar in reply to Daniel Link to this post

    Thanks--I will try that.

    How do I handle the case where the user enters a value that's not in the list in this case? How does the new value get passed back?

  5. Daniel
    Admin
    Daniel avatar
    2118 posts

    Posted 09 Mar Link to this post

    Hello again,

    The custom value will be sent to the server but in most cases it will not be bound by the model binder. If custom values should be allowed then you could retrieve it from the ModelState or from the request data:
    if (ModelState["Part.Id"].Errors.Any())
    {
        var customValue = ModelState["Part.Id"].Value.AttemptedValue;
        ModelState.Remove("Part.Id");
        AddCustomValue(customValue);
    }
     

    Regards,
    Daniel
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  6. Bill Wingate
    Bill Wingate avatar
    12 posts
    Member since:
    Feb 2009

    Posted 10 Mar in reply to Daniel Link to this post

    Binding to model.Part.Id worked for the ComboBox. Maybe this should be a new thread, but the next problem is that I have the ComboBox in a Grid.

    To get the grid to show the part name instead of part ID when the cell isn't in edit mode, I have to have a ClientTemplate:

    columns.Bound(p => p.Part.Id).EditorTemplateName("PartComboBox").ClientTemplate("#= Part.Name #");

    That works until I enter a new custom value in the ComboBox. The ComboBox shows the value, but once I leave Edit mode for the cell, the grid shows "undefined" for the value. How do I get it showing the new value?

  7. Daniel
    Admin
    Daniel avatar
    2118 posts

    Posted 14 Mar Link to this post

    Hello,

    If the same editor is used for a grid then I can suggest either to use a ForeignKey column for the Part.Id field or bind the column to the object and explicitly specify the binding in the editor via the HtmlAttributes method:
    columns.Bound(p => p.Part)
    Html.Kendo().ComboBoxFor(model => model.Part.Id)
        .HtmlAttributes(new { data_bind = "value:Part"})
        ...
    This way the Id field will be posted correctly with the form but the object will be bound when using the editor for the grid. Using a separate editor for the grid is another option.


    Regards,
    Daniel
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  8. Bill Wingate
    Bill Wingate avatar
    12 posts
    Member since:
    Feb 2009

    Posted 14 Mar in reply to Daniel Link to this post

    I wasn't able to successfully apply either of those approaches in my scenario.

    I have another class called "Assembly" that has a collection of Parts. On the edit page for an Assembly I have a grid bound to the Parts collection:

    My grid definition is:

    @(Html.Kendo().Grid(Model.Parts)
                        .Name("Parts")
                        .Columns(columns =>
                        {
                            columns.Bound(p => p.Quantity);
                            columns.Bound(p => p.Part.Id).EditorTemplateName("PartComboBox").ClientTemplate("#= Part ? Part.Name : '' #");
                            columns.Bound(p => p.Instructions);
                            columns.Command(command => command.Destroy()).Width(100);
                        }
        )
        .Navigatable()
         .Editable(edit => edit
             .Mode(GridEditMode.InCell)
             .CreateAt(GridInsertRowPosition.Bottom)
         )
         .DataSource(datasource => datasource
             .Ajax()
             .Model(model =>
             {
                 model.Id(p => p.Id);
                 model.Field(p => p.Part).DefaultValue(new Models.PartViewModel());
             })
                )
     
     
     
    )

    The PartComboBox editor template is this:

    @(Html.Kendo().ComboBox()
            .Name("Part")
            .DataValueField("Id")
            .DataTextField("Name")
            .Filter(FilterType.Contains)
            .DataSource(source =>
            {
                source.Read(read =>
                {
                    read.Action("GetParts", "RefData").Data(@<text>
            function()
            {
                var val=$("#Part").data("kendoComboBox").input.val();
            return {
                Name: val}
            }
                    </text>);
                })
                .ServerFiltering(true);
            }
            )
    )

    I tried modifying this to apply the data_bind attribute to the ComboBox but that didn't change anything. I don't understand how to adapt the foreign key demo to my setup.
  9. Daniel
    Admin
    Daniel avatar
    2118 posts

    Posted 16 Mar Link to this post

    Hello,

    I am not sure if i understand correctly the issue but if you wish to submit the grid data with a form as part of the assembly then you can use the approach demonstrated in this code-library project.

    Regards,
    Daniel
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  10. Bill Wingate
    Bill Wingate avatar
    12 posts
    Member since:
    Feb 2009

    Posted 21 Mar in reply to Daniel Link to this post

    I'm not trying to submit the grid as part of the form.

    My problem is that if I bind using the ComboBox like this:

    columns.Bound(p => p.Part.Id).EditorTemplateName("PartComboBox");

    The cell (when not in edit mode) shows the part ID rather than the part name. I can fix that by changing to:

    columns.Bound(p => p.Part.Id).EditorTemplateName("PartComboBox").ClientTemplate("#= Part ? Part.Name : '' #");

    That works until I enter a new custom value in the ComboBox. The ComboBox shows the value, but once I leave Edit mode for the cell, the grid shows "undefined" for the value.

    I tried various approaches of binding to "p.Part" instead of "p.Part.Id" but that doesn't work either. I either end up with the cell showing nothing or showing "[object Object]".

  11. Daniel
    Admin
    Daniel avatar
    2118 posts

    Posted 23 Mar Link to this post

    Hi,

    It seems the approach with explicitly specifying the binding will not work for the combobox. Because of the name generated for the text input the correctly bound object will be overridden. In that case I can suggest to use a separate editor for the grid or to remove the text input name via code or to use a foreignkey column. I attached a sample project that demonstrates the suggested solutions.

    Regards,
    Daniel
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  12. Bill Wingate
    Bill Wingate avatar
    12 posts
    Member since:
    Feb 2009

    Posted 28 Mar in reply to Daniel Link to this post

    The demo solution you posted is showing problems similar to what I have been describing.

    In the top grid ("Parts"), select a cell and enter a value that's not from the list, like "Part 109". When you leave the cell, it shows "undefined."

    In the bottom grid ("PartsForeignKey"), if you enter a non-existent value the cell is empty when you leave it.

  13. Daniel
    Admin
    Daniel avatar
    2118 posts

    Posted 31 Mar Link to this post

    Hi,

    The foreignkey column cannot be used for custom values because it can only show values available in the data that is passed initially on the server. The problem with displaying the value when binding to object can be avoided by changing the logic in the template but the binding will not work correctly after setting a custom value because the field will no longed be an object. Custom binding might be the best option for this scenario. I attached the project modified to demonstrate one possible implementation.

    Regards,
    Daniel
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  14. Bill Wingate
    Bill Wingate avatar
    12 posts
    Member since:
    Feb 2009

    Posted 05 Apr in reply to Daniel Link to this post

    Thank you--that seems to be working.

    The last piece is that I need to do server filtering for the combo box data source, based on the entered text. I previously had this working, but since I adapted to use your code it's not. What is the id of the combo box now?

    I have this for the data source:

    source.Read(read =>
    {
        read.Action("GetParts", "Home").Data(@<text>
    function()
    {
    var val=$("#Part").data("kendoComboBox").input.val();
    return {
    userId: @ViewBag.UserId,
    Name: val}
    }

    But using "#Part" doesn't work. How do I get the current value of the combobox?
  15. Daniel
    Admin
    Daniel avatar
    2118 posts

    Posted 07 Apr Link to this post

    Hi,

    The id that will be generated by default would be "Part_Id". You can also use the HtmlAttributes method to set any ID to the input:
    .HtmlAttributes(new { data_bind = "customValueObject:Part", data_skip="true", id = "Part"})


    Regards,
    Daniel
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  16. Bill Wingate
    Bill Wingate avatar
    12 posts
    Member since:
    Feb 2009

    Posted 07 Apr in reply to Daniel Link to this post

    I hadn't noticed that the sample you sent had the ID set to a Guid using the HtmlAttributes. Now I see.

    Thanks for the help; I think I have this all working now.

Back to Top
UI for ASP.NET MVC is VS 2017 Ready