Hi Telerik,
the dropdownlist does not select the correct option on initialization when using virtualization (if i turn off virtualization it works fine). Im using it very similar to your demo of virtualization.
Is it possible that this is a bug? Im using version 2015.1.429.545.
this is my code:
@(Html.Kendo().DropDownListFor(model => model.person_id)
.DataTextField(
"Name"
)
.DataValueField(
"Id"
)
.Filter(
"contains"
)
.OptionLabel(
"Choose..."
)
.Height(300)
.DataSource(source =>
{
source
.Custom()
.ServerFiltering(
true
)
.ServerPaging(
true
)
.PageSize(80)
.Type(
"aspnetmvc-ajax"
)
.Transport(transport =>
{
transport.Read(
"ReadForDropDown"
,
"Person"
);
})
.Schema(schema =>
{
schema.Data(
"Data"
)
.Total(
"Total"
);
});
})
.Virtual(v => v.ItemHeight(26).ValueMapper(
"personsValueMapper"
))
)
5 Answers, 1 is accepted
In general, the widget will select the index that is returned from ValueMapper function, as it represent the item index of the selected value. Could you verify that the valueMapper callback returns the correct index of the value? Could also let us know what is the difference between the selected value and the real selected item as number offset? A repro demo will be of a great help.
Regards,
Georgi Krustev
Telerik
Hi Georgi,
[quote]Georgi Krustev said:
In general, the widget will select the index that is returned from ValueMapper function, as it represent the item index of the selected value
[/quote]
Ok, that helped me to find out, whats going on... the ValueMapper calculated the index based on a sorted liste, while the ToDataSource-Extension in the ReadForDropDown-function removes the sort-order of this list => different indexes...
So far so good, but how can i sort the dropdownlist with virtualization?
this also seems not to work:
.DataSource(source => { source.Sort(srt => srt.Add("Name").Ascending()); })
Regards,
Xaver
Basically, the sorting will not be applied by the ToDataSource (and thus removed) if it is not present in the DataSourceRequest info. Could you verify that the sort expression is properly passed to the ToDataSource extension method? If it does and the problem still persists, would it be possible to send us a repro demo that we can investigate further? This will give us an understanding of your implementation and will help us to narrow the problem down much faster.
Regards,
Georgi Krustev
Telerik
Hi Georgi,
thanks for your help again! So i got virtualisation with a sorted list to work now (had to add .ServerSorting(true)), you can see full code below.
But I have still a view questions:
- By now i have to sort in the valueMapper function in controller AND again in the widget. Is there a way to sort it only once?
- I use this as a partial view very often, sometimes the Person_id is nullable and somtimes not. So when the Person_id is null the loading-squiggle is rotating until you click on the widget and not selecting the optionLabel, if Person_id is 0 everything works fine. Do you know a solution for it?
- If the user filters the dropdownlist and removes his input again, the readfordropdown function returns an empty list (request filter = Name~contains~''). Is there a easy solution for it?
razor code:
@(Html.Kendo().DropDownListFor(model => model.person_id)
.DataTextField(
"Name"
)
.DataValueField(
"Id"
)
.Filter(
"contains"
)
.OptionLabel(
"Choose..."
)
.Height(300)
.DataSource(source =>
{
source
.Custom()
.ServerFiltering(
true
)
.ServerPaging(
true
)
.PageSize(80)
.Type(
"aspnetmvc-ajax"
)
.Transport(transport =>
{
transport.Read(
"ReadForDropDown"
,
"Person"
);
})
.Schema(schema =>
{
schema.Data(
"Data"
)
.Total(
"Total"
)
})
.Sort(srt => srt.Add(
"Name"
).Ascending())
.ServerSorting(
true
);
})
.Virtual(v => v.ItemHeight(26).ValueMapper(
"personsValueMapper"
))
)
JavaScript code:
function
personsValueMapper(options) {
$.ajax({
url:
'../Person/Persons_ValueMapper'
,
data: personsConvertValues(options.value),
success:
function
(data) {
options.success(data);
}
});
}
function
personsConvertValues(value) {
var
data = {};
value = $.isArray(value) ? value : [value];
for
(
var
idx = 0; idx < value.length; idx++) {
data[
"values["
+ idx +
"]"
] = value[idx];
}
return
data;
}
controller code:
public
ActionResult ReadForDropDown([DataSourceRequest] DataSourceRequest request)
{
var result = from p
in
_personService.Read() select
new
{ Id = p.Id, Name = p.Name };
DataSourceResult dataSourceResult = result.ToDataSourceResult(request);
return
Json(dataSourceResult, JsonRequestBehavior.AllowGet);
}
public
ActionResult Persons_ValueMapper(
int
[] values)
{
var indices =
new
List<
int
>();
if
(values !=
null
&& values.Any())
{
var index = 0;
foreach
(var person
in
_personService.Read().OrderBy(p => p.Name))
{
if
(values.Contains(person.Id))
{
indices.Add(index);
}
index += 1;
}
}
return
Json(indices, JsonRequestBehavior.AllowGet);
}
Regards,
Xaver
Up to your questions:
#1: I am afraid that you will need to post in both places, as the one is used to sort/page/filter the data (the service that binds the widget) and the other is used to calculate the item index, which will not be correct if the source is not filtered, sorted and grouped correctly.
If you do not want to calculate the value index, then I will suggest you just cache a value<->index map, that will decrease the calculation time a lot.
#2: This sound as an issue, that we addressed in our internal builds. Could you upgrade to the latest internal build and let us know whether the behavior is still observable?
#3: The widget is designed to perform a request when the input is cleared. We are doing this to allow the users that would like to show something on empty list to catch that request. For those who want to skip this behavior, they will need to prevent the filtering in the filtering event like so:
function filtering(e) {
if (e.filter.value === "") {
e.preventDefault();
}
}
Regards,
Georgi Krustev
Telerik