Unplanned
Last Updated: 10 Mar 2023 18:07 by Peter
Michal
Created on: 01 Dec 2022 10:11
Category: ComboBox
Type: Bug Report
2
Event ValueMapper+multiple OnRead is firing multiple times even when mapping exists

Hello,

 iam found "strange" behaviour compared to previous versions in combobox, with custom paging, filtering, valuemapper.

"simple description":
- Do not call OnRead and ValueMapper AFTER clicking/selecting the ITEM in any case(after filtering, or after scrolling...). Do it same way as selecting WITHOUT prior filtering.

Complex test

A sample for testing is here(and comments inside):
https://blazorrepl.telerik.com/GGPwalvk09g228sm32

How to reproduce:

1 - start = value is PREselected - OK
2 - clear the combobox - OK
2 - input value 40  - slowly do not rush, number by number - OK
3- wait 2 seconds and Click/select item ("Name 401" etc) - NOK
observe the events fired(Exception/info: time - indicates that OnRead was fired again) 

Repeat the same WITHOUT filtering, just scrolling
observe the events fired = looks ok (Exception/info: time)

When selecting item by CLICKING on it(after filtering) looks like those events are fired:
- ValueMapper (why?)
- OnRead again(why again?)
- bind value (ok)
and sometimes ValueMapper again
it depends of "timing"

expected:
When selecting item by CLICKING on it:
- BIND the value. Everything is in there(no reason to call OnRead or ValueMapper)

Related, unexpected(video attachment):
Also when working in "real" scenario, AFTER clicking on item AFTER filtering, it returns full MODEL assembly path into to input filed, instead of clicked item
Lets have a list: {Name of the item,Another item,Next item}
entere in combobox/filter "name", results are shown ok, clicked on one and result shuld be ("Name of the item"), after clicking it returns "base model class name"
ie: "inwApp1.Pages.prozam.crm.EdcrmOrg+BaseKeyModel" - you dont want to see this :) .

There is different event orders for those 2 scenarios(it should be the same for both as at point 1) ):
1) when SELECTing item without filtering(just moving with scrollbar down to value 401 (only with onread and virtual paging)) = OK
2) when filtering by value "40" and SELECTing item by clicking on it - NOT OK = it look like this causes the problems and subsequent event calls

Is there any workaround, or new "property" to set? Thanks

Attached Files:
6 comments
Peter
Posted on: 10 Mar 2023 18:07

The trick seems to be to hook into OnOpen and OnClose and to set a private field `IsOpen` to true or false.

When `IsOpen` is `true` then the DropDownList is performing a filter search. When it is `false` then it is trying to retrieve an entry for the current value.

So what you can do is (pseudo code)

When Open
(Do your normal thing)

When closed

  1. If the new key != CachedKey
    1. CachedItem = Fetch the single item
    2. Set CachedKey = key
  2. If CachedItem is null then set args.Total = 0 and args.Data = Array.Empty;
  3. Otherwise set args.Total = 1 and args.Data = an array with only CachedItem in it

 

  1.  

Michal
Posted on: 13 Dec 2022 12:02
Hello Dimo,

 thanks for the info.

Until then, i hope that DropDownList doesnt get this also(in 3.7.0 is working ok so far).

So its up to Your team, which way you prefer, all of them leads to better ending:
- call OnRead AFTER the valuemapper*
OR
- do not call valuemapper when value is there
OR
*Iam get the point, that with the reset, you want later show to the user "first" resultset when they open the popup again. Its nice idea, no problem for the users :) 
Perhaps an even better option maybe to do loading after popup opens.
ADMIN
Dimo
Posted on: 13 Dec 2022 06:39

Hi Michal,

Here are a few additional comments:

  • "Unplanned" state means that we will fix the problem in a future release, but it's still not clear which one. Since this is a regression, I expect a more expedite time frame.
  • Closing the ComboBox will continue to reset (remove) the current filter and this will continue to call OnRead. This is by design. If your scenario is to show data only after filtering, then the user does not see anything inside the ComboBox dropdown on initial page load as well.
  • The provided REPL example does not include a ValueMapper, which is required for virtual scrolling. That's why the user doesn't see the selected Value.

Regards,
Dimo
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Michal
Posted on: 13 Dec 2022 05:57

According to unplanned state - how to fix it?:

On one side thanks for suggestion, but unfortunately it doesnt working also. Situation is even worse, its about NOT ABLE to use combobox anymore with ComplexObjectModel(keyvalue and textvaule) binding(not just simple value) and EXTERNALL datasource which doesnt not support fetching data by KEYvalue, but only filtering by textvalue.
As You said, is it future expected behaviour?: "if the user filters and then selects a value or closes the dropdown, this will reset the current filter"*** = But then the user see NOTHING**.

Even WITHOUT ValueMapper, OnRead is called when it should not and also with WRONG values:
https://blazorrepl.telerik.com/mQvGPnkJ27ZoToJC11

1 type in combobox 401
2 click on "Name 1401"
3 OnRead is called, and combobox is EMPTY** = there shloud be selected value. Unnecessary call, and what more with wrong arguments(filtering,skip...)

Can you manage to fix it?I bet, that fixing this, also fix the valuemapper which is called AFTER the wrong OnRead.

***Documentation says it correctly, but combobox doesnt behave like this:
https://docs.telerik.com/blazor-ui/components/combobox/events#onread
OnRead
The event fires when:

the component initializes
the user filters
the user scrolls with virtualization enabled

problem is this:
+ event firews when "the user select the item after filtering" which is terrible idea + with wrong/unexpected values.

Imagine remote datasource(most of them), where you can only filter by name,page,offset... , NOT by some id/key value. Most of them - as in the example and you are out of the luck.

 

Something positive:
- DropDownList is working ok as expected, as documentedThanks

Michal
Posted on: 12 Dec 2022 14:53

Hello Dimo,

 thanks Iam looking forward. Right now its really breaking change, for all comboboxex with valuemapper and only options was revert to previous version. Iam using it heavily as documentation says: "Usually, this method will be called on the initial render only to fetch the data item for the current selection".

In the meantime "Related, unexpected scenario" with previous video attachment, has the simple answer/cause:
- yes, its related to the event ValueMapper, because is firing when it should not. It happens when ValueMapper returns the NULL(string) value in TextField.
So this one will fix itself, when the valuemapper gets fixed :)

ADMIN
Dimo
Posted on: 08 Dec 2022 09:15

Hello Michal,

Thanks for the test page and video.

If the user filters and then selects a value or closes the dropdown, this will reset the current filter. By design, any change in the data state triggers a new OnRead call.

With regard to the ValueMapper, I agree it makes sense to avoid the additional call if the component preserves the selected data item before calling OnRead. It also looks like this behavior changed in 3.7.0. I asked our devs to take a look and when I have more information, I will update the status here.

In the meantime, if you want to optimize the number of remote requests by the ValueMapper, my suggestion is to cache the selected model in ValueChanged and provide it in the subsequent ValueMapper call.

The code below is using your example as a base. Yellow means changed and green means added:

<TelerikComboBox
                 Value="@SelectedValue"
                 ValueChanged="@OnValueChanged" />

@code {
    Person CachedModel { get; set; }

    async Task OnValueChanged(int? newValue)
    {
        SelectedValue = newValue;
        if (newValue != null)
        {
            CachedModel = new Person() { Id = SelectedValue, Name = $"eeeeXX {SelectedValue}" };
        }
        else
        {
            CachedModel = null;
        }
    }

    Task<Person> GetModelFromValue(int? selectedValue)
    {
        if (selectedValue == null) return null;

        if (CachedModel != null) return Task.FromResult<Person>(CachedModel);

        var result = new Person { Id = selectedValue, Name = $"eeeeXX {selectedValue}" };
        return Task.FromResult<Person>(result);
    }
}

Regards,
Dimo
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.