Completed
Last Updated: 02 Jan 2024 13:48 by ADMIN
Developer
Created on: 29 Mar 2021 00:10
Category: DropDownList
Type: Bug Report
0
Automation of tab/enter keys causes field to fail validation
Hi, I am trying to enhance data entry in dropdown lists by using the tab and enter keys to move the focus to the next field after an entry in the list is selected using the up/down arrows or dropdown list filter textbox. While it is working, if the form validator's validateOnBlur setting is set to true, a required field message is displayed even though a value has been selected.

My code is below. How do I get the field to validate after losing the focus?
	var DropDownList = (function (init) {
		return kendo.ui.DropDownList.extend({
			init: function (element, options) {
				var that = this;
				init.call(that, element, options);

				that.wrapper.keydown(function (e) {
					if (e.ctrlKey && e.shiftKey) {
						that.open();
						return;
					}

					var keyCode = e.keyCode || e.which;

					if (keyCode !== 9 && keyCode !== 13) {
						that.open();
					}
				});

				$(that.filterInput).bind("keydown", function (e) {
					var keyCode = e.keyCode || e.which;

					if (keyCode === 9 || keyCode === 13) {
						var press = jQuery.Event("keydown");
						press.ctrlKey = false;
						press.keyCode = 13;
						press.which = 13;
						$(that.wrapper).trigger(press);
					}
				});
			},
			options: {
				name: "DropDownList",
				dataValueField: "Value",
				dataTextField: "Text",
				filter: "contains",
				minLength: 1,
				ignoreCase: true,
				animation: false,
				valuePrimitive: true
			}
		});
	})(kendo.ui.DropDownList.fn.init);

	kendo.ui.plugin(DropDownList);

12 comments
ADMIN
Veselin Tsvetanov
Posted on: 05 Apr 2021 13:51

Hi,

Thank you very much for your patience and for the multiple examples that you have prepared.

The reason I was observing different behavior is the fact that I have substituted the jQuery version used in your app (3.2.1) with version 1.12.3. That being said, the older value reported within the widget change event should be regarded as a jQuery-related bug in the DroDownList widget. Here is the GitHub item I have opened on the above:

https://github.com/telerik/kendo-ui-core/issues/6363

As a small token of gratitude for reporting the above, I have updated your Telerik points.

As a temporary workaround, if that is viable for your application, I could suggest you using jQuery version 1.X or 2.X. 

Once again, thank you for your efforts.

Regards,
Veselin Tsvetanov
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Developer
Posted on: 02 Apr 2021 23:24

Sorry, but my sample project had a couple of bugs. Attached is a revised version.

In order to fully implement the "Html.Kendo().DropDownListFor(m => m.OrderId)" functionality, uncomment the row in HomeController.GetDropDownListValue(). You will notice a change of behaviour when tabbing, which I don't quite understand. It seems to me though that getting the value mapper functioning in the right way is the key to the problem.

Developer
Posted on: 02 Apr 2021 22:41

Hi Veselin, the thing is, if you understand what's going on then there must be some way to reproduce the behaviour. As I have already mentioned, I believe there is a race condition happening between my jQuery code and the value mapper function. 

With this is mind, I have attached an updated project with some changes:

1. In site.js, I have added a one second delay to the function ValueMapper(), although I'm not sure this will help. Perhaps you can come up with a better idea.

2. Just to clarify your point about the lack of validation errors, it is important to understand what I have been saying here. In this project, the value of the dropdown list was NEVER NULL, meaning validation would never fail. My point was about what was happening in the change event, not validation.

Having said that, I have provided an option to test validation. In Index.html, change the code "Html.Kendo().DropDown()" to "Html.Kendo().DropDownListFor(m => m.OrderId)" and uncomment the validator initialisation. The dropdownlist will initially be set to null and fail validation only if the behaviour can be reproduced.

3. If all else fails, try setting the control's AutoBind property to false, which changes behaviour slightly.

ADMIN
Veselin Tsvetanov
Posted on: 02 Apr 2021 11:44

Hi,

Thank you for the additional information provided.

I have run the sample again and I have observed exactly the same behavior as recorded on the previously attached screencast. These are the exact steps that I follow on that video:

1. Run the sample

2. Click with the mouse on the DropDownList, so that its pop-up opens

3. Type "32"

4. Press Tab

5. The alert box displays: "Value changed to 32"

I have also tried a similar scenario in which I set initially using the mouse the value of the DropDownList to null (by selecting its OptionLabel). Then I follow the above steps. The result is exactly the same - the alert displays "Value changed to 32". Moreover, no validation errors are shown.

Because what I have observed and recorded differs from what you have observed at your end, if convenient for you, I would like to invite you to a Remote Assistance session. As per our support policy, I am available between 8 AM and 2 PM UTC, Monday to Friday. Please, let me know about a slot that would be convenient to you (if any), so we can review the case together in your dev environment.

Regards,
Veselin Tsvetanov
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Developer
Posted on: 01 Apr 2021 23:40

Hi Veselin, there are actually two things you are missing. The most important thing was:

The previous value is returned in these cases, which is why we are getting validation errors when the previous value is null.

In this sample project the previous value is never null so the validation doesn't fail, but this behaviour is secondary to what is happening. Please try it again, except this time, please take note of what I said about the alert box:

1. Type "32".

2. Press Tab or Enter.

3. The alert box will report "Value changed to 1".

Now reload the page and do the following:

1. Type "32".

2. Select the value with the mouse.

3. The alert box will report "Value changed to 32".

Do you understand what I'm saying? Using the Tab or Enter key results in the OLD VALUE being returned.

As I have mentioned previously, In spite of this fact, if validateOnBlur is set to FALSE, the CORRECT VALUE is returned in the model when the form is submitted.

ADMIN
Veselin Tsvetanov
Posted on: 01 Apr 2021 16:09

Hi,

Attached you will find a short screencast on which I run the application send and I follow these steps:

- Focus the DropDownList by using the mouse;

- Type "32";

- Press Tab;

You will notice that the newly selected value is 32. Also, the Validator does not report any errors.

Am I missing something? Does the sample need some additions in order to reveal the issue?

Regards,
Veselin Tsvetanov
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Attached Files:
Developer
Posted on: 01 Apr 2021 05:53

Hi Veselin, I have attached a sample project that reproduces the behaviour.

To reproduce it, select the dropdown list and enter a value outside the page size of 20 (say 32), then press the enter or tab key. An alert will then display the value. The trick is to not use the mouse except for setting the focus on the widget.

Having created this project, I now see what's happening. The previous value is returned in these cases, which is why we are getting validation errors when the previous value is null. But the thing is, the change event is fired every time, which is what makes the alert box display.

ADMIN
Veselin Tsvetanov
Posted on: 31 Mar 2021 14:49

Hello,

The wrapper and the element nodes will react to different triggers. This way, raising a key event should be done on the wrapper (just like you did), while raising the change event should be done on the element.

As per the other questions, I will need to be able to replicate and review the scenario (and the issue) locally. This way I will be able to properly answer whether and if yes, at what point the value() method should be called. It will also allow me to review the validation issue and identify the exact cause for it. Otherwise, my suggestions are based on some guesses that may not be applicable to your scenario.

Keep also in mind that there are some limitations that might be hit upon extending the DropDownList widget. I do not believe that is the case in the scenario in question, but without having the full information I could not be certain on that.

Looking forward to hearing from you.

Regards,
Veselin Tsvetanov
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.

Developer
Posted on: 31 Mar 2021 00:10

Hi Veselin, I should have been clearer with my question about syntax. While I understand the difference between wrapper and element, I wanted to know how each implementation may differ in this context. After some further testing I found that my method using $(that.wrapper) works, while using that.element doesn't.

I'm not sure what you're saying about widget.value(). How do I set it? Since the purpose of my code is to select a value through keyboard events, the value isn't available until the events are completed, and I know for a fact that the change event is being fired after the keydown event is processed. Surely this must indicate that the widget has accepted the selection that was made?

In any case, it doesn't make sense that validateOnBlur=false works without any validation failures. In other words, setting it to true results in a validation failure, while setting it to false results in a validation success when the form is submitted. What this tells me is that there is a race condition happening during the validateOnBlur process that is producing a false negative. How do I ensure the value has been set before the validation takes place?

ADMIN
Veselin Tsvetanov
Posted on: 30 Mar 2021 09:40

Hello,

I beg your pardon for not explaining clearly the idea behind my suggestion. It aims to trigger the change event of the DropDownList <select> / <input> element (that.element or this.element) and not the widget itself. That is needed because the Validator will listen for changes on the element and not on the widget itself. 

As per your questions, yes, you will need to trigger the change event after the selection in the widget has been made. Also, as explained above, the that.element is the input/select element of the DropDownList, which holds the actual selected value in the widget. The that.wrapper, on the other hand, is the element that holds the entire rendering of the DropDownList.

Concerning your final question, the valueMapper of the DropDownList will be called when trying to set a value that is not present in the current view of the DataSource. Therefore, to call the remote valueMapper you could use the .value() method of the widget.

Once again, if you face any further issues, please, send me a small isolated sample demonstrating them. This way I will be able to troubleshoot the case locally and to provide you with the most appropriate assistance on that.

Regards,
Veselin Tsvetanov
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Developer
Posted on: 29 Mar 2021 12:27

Hi Veselin, since my jQuery code is triggering the keydown event, the widget's change event is subsequently triggered anyway. I tested and confirmed that your method doesn't work.

I'm not even sure that your method is the correct way to achieve this. Since the keydown event is jQuery's first key event, wouldn't it precede the change event, in which case the selection is sure to be made prior to the change event being triggered? Or does this not matter?

Also, I see that you are using the syntax "that.element", whereas I am using "$(that.wrapper)". Are there any differences between the two?

After doing some further investigation, I may have discovered what's happening here. What I initially thought was inconsistent behaviour seems to be down to the use of custom datasources of type "aspnetmvc-ajax" with value mapping for large lists. Is there a method I can employ to trigger the value mapping, or is there some other way to do it?

ADMIN
Veselin Tsvetanov
Posted on: 29 Mar 2021 11:08

Hi,

The validation state should be updated upon Widget input element value change. In the described scenario, as the value of the DropDownList is programmatically changed, you will need to manually call the element change event:

that.element.trigger("change");

If the above does not help. could you, please, prepare a small sample demonstrating the issue in question? You could use our Dojo sandbox to prepare that demo:

https://dojo.telerik.com/EkUnifUx/3

In case you have any other questions, please do not hesitate to contact us.

Regards,
Veselin Tsvetanov
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.