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

Initial values serialization problem using wrapper

4 Answers 147 Views
MultiSelect
This is a migrated thread and some comments may be shown as answers.
Ori
Top achievements
Rank 1
Ori asked on 13 Mar 2015, 03:19 PM
Hi,
I've come accross a very strange behavior of multiselect wrapper in a certain situation. I'm either not using the control properly or maybe it could be a wrapper bug.
The model contains two properties:
 - ItemIds (to be Posted back on submit)
 - Items (contains complete objects, with all properties for presenting like Code, Name and Id)

The initially preselected Model.Items are directly put into the code on the server, rest of items user can select is loaded via AJAX.

@(Html.Kendo().MultiSelectFor(x => x.ItemIds)
        .DataValueField("Id")
        .TagTemplate("#:data.Code# - #:data.Name#")
        .ItemTemplate("#:data.Code# - #:data.Name#")
        .AutoBind(false)
        .Value(Model.Items)
        .DataSource(d => d.Read(r => r.Action("GetItems", "ItemService").Data("getAdditionalData"))
        .ServerFiltering(true))
)

So, when the page is loaded, the MultiSelect contains some initially preselected items (properly serialized as objects in the javascript code), we can add some more, post them back. So far so good.

But - when we add some validation (no matter which control contains invalid data) and the ModelState in the controller becomes invalid, the javascript serialization of the .Value(Model.Items) doesn't serialize all object properties (like Code, Name and Id) but only the Id property. So there are no initially preselected items in the multiselect.
I'm 100% sure the Model.Items contains all the information in both situations - no matter if the model state is valid and invalid. 

I've also a workaround for this problem. Do not use the wrapper - use the javascript and serialize the Model.Items manualy like this:

01.$(selector).kendoMultiSelect({
02.                "dataSource": {
03.                    "transport": {
04.                        "read": {
05.                            "url": "/ItemService/GetItems",
06.                            "data": getAdditionalData
07.                        },
08.                        "prefix": ""
09.                    },
10.                    "serverFiltering": true,
11.                    "filter": [],
12.                    "schema": { "errors": "Errors" }
13.                },
14.                "itemTemplate": "#:data.Code# - #:data.Name#",
15.                "tagTemplate": "#:data.Code# - #:data.Name#",
16.                "autoBind": false,
17.                "dataValueField": "Id",
18.                "value": @Html.Raw(Json.Encode(Model.Items))
19.            });

But this workaround complicates other things and I really would prefer to use the wrapper instead of this. 

Thanks,

Ori

4 Answers, 1 is accepted

Sort by
0
Daniel
Telerik team
answered on 17 Mar 2015, 10:40 AM
Hello,

As all other HTML helpers, the multiselect will set the value from the ModelState if available which will be the posted Id value. You could remove the ModelState entry for the multiselect property in the post action:
ModelState.Remove("ItemIds");
so that the value is populated from the model in both cases.

Regards,
Daniel
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Ori
Top achievements
Rank 1
answered on 26 Mar 2015, 02:11 PM
Hi, 
I've tried this advice, it works - but, there are two problems that make it unusable in the real world:

1) A fatal one - if I remove an item from ModelState like this, I also remove validation errors, so if "ItemIds" MultiSelect was posted with invalid data, the validation message never gets it to the CSHTML control @(Html.ValidationMessageFor(x => x.ItemIds))

2) How can I use this advice for all Kendo widgets that have ajax datasource? It would not be systematic to always call ModelState.Remove for certain Model properties in HttpPost Controller Actions. 
0
Daniel
Telerik team
answered on 30 Mar 2015, 09:37 AM
Hello again,

You could clear just the value if validation is used for the property:
ModelState["ItemIds"].Value = null;
As for your other question - you could create a custom helper or an extension method for the widget that does this automatically e.g.
public static class KendoExtensions
{
    public static MultiSelectBuilder ModelValue(this MultiSelectBuilder builder, IEnumerable value)
    {
        builder.Value(value);
        var component = builder.ToComponent();
        var modelEntry = component.ViewData.ModelState[component.Name];
        if (modelEntry != null)
        {
            modelEntry.Value = null;
        }
        return builder;
    }
}
Html.Kendo().MultiSelectFor(x => x.ItemIds)
    .ModelValue(Model.Items)


Regards,
Daniel
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Ori
Top achievements
Rank 1
answered on 30 Mar 2015, 11:56 AM
That's awesome solution! 

Thank you
Ori
Tags
MultiSelect
Asked by
Ori
Top achievements
Rank 1
Answers by
Daniel
Telerik team
Ori
Top achievements
Rank 1
Share this question
or