BUG - see Issue 2
Undesired behaviour - see Issue 1
Issue 1
With combo-boxes and placeholders, when we do filter items and press ENTER (without selecting any of the items) we get 1st item selected from the list. With drop-down-list, we always get the default item selected.
Based on https://github.com/telerik/kendo-angular/issues/319 the defaultItem is meant to be a replacement for the placeholder, yet it does behave differently.
Issue 2
Using dropdownlist and filtering and defaultItem together when there's a value on the filter, it's impossible to select the defaultItem (nor via mouse, neither via keyboard).
Also inside the comments there are 4 questions based on what developers maybe would be able to achieve a solution for the Nr. 2. issue, if some hints would be provided.
https://stackblitz.com/edit/valid-selection-withfilter-wont-allow-default-to-be-sele-vpt2yo?file=app/app.component.ts - With comments on the TS on reproduce some of the issues.
StackBlitz or Angular 4.x, Chrome (latest)
Dear Telerik,
I would like to thank you for the suggested soluitions (Ticket ID: 1348425), yet I need to express that those are hardly useable workarounds for different reasons.
Use combobox instead of dropdownlist is not a solution.
FACTS:
The concept of a selectable default item as a replacement for a placeholder simply smells.
Some background (for others reading this issue): Combobox does not have a selected item (value) template, so assume its the reason why a plain placeholder text is used there. Dropdownlist has selected item template (value template), so it makes sense to use something more sophisticated than just a plain string to display - but anyhow - if it serves the same purpose, it should behave similarly (not being selectable, maybe not even show up inside the drop-down items). also calling it placeholderItem would possibly make more cleaner what it is intended for.
Based on that background my original suggestion (drop default item, add X button, add placeholder support) has to be modified as follows:
SUGGESTION:
This would of course also remove the need to address the issue of default item not being selectable with non empty filter expression.
Above changes would result in a very similar searching experience as with combo-boxes (which users do like) . So something similar as No-data template, just for the selected value.
Current issue:
The issue can be checked here (stackblit provided by Telerik):
Of course having a way to add multiple (not necessarily just one) item(s) before a selection is also a good solution, but for something else. I use it to show selected item (id / text) that I loaded from the server, without the need to fetch items into the combo-box (as the combo box uses > 5.000 items and serer side filtering). i called that input InitialData and it's a part of my search-ex directive which supports advanced odata and local array filtering over multiple properties.
Anyhow if TELERIk will keep the current behaviour, the first thing that I'll do is to try to create a directive which will simply override this behaviour, and for that we will need:
1) a way to unselect default item on pop-up opening
2) be able to tell if user pressed ENTER or ESC (so we know if we we need to select 1st item from list if we hit ENTEr or simply leave selection/default if ESC is pressed)
...and I assume our team won't be the only one searching for similar, good old standards...
@hidegh The default item should indeed be selectable when there's a filter query in place and we'll look to resolve the issue as soon as possible. Thank you for pointing this out.
About the other questions raised:
If you weren't satisfied with the proposed solution in the support ticket thread, you could have just asked for a different solution there - the GitHub repo is for reporting issues with the components and not for asking questions on how to achieve some custom functionality that is not supported out of the box.
Anyway, you can refer to this example that gives you a placeholder-like functionality and a reset button.
@dimitar-pechev
TX for the way to emulate placeholder correctly.
Reasons for creating a BUG were:
Still some shortcomings:
1)
You mentioned that During filtering the focus should jump to the first item after the default one - actually not working in every case. Provided a tackblitz: here. Just select the default item. Then re-open the dropdown, enter serach text: s, press ENTER - the default item is the one that has been kept as the selection, not the 1st avail. one. So this is not working so (or not in every case).
Also updated original comment (with proper note).
Btw: is there a way to intercept selection event (while pop-up is opened) and keyboard events (from pop-up) so we can code our own bypass?
2)
Creating a reset button via wrapping - it's not a hello world app people wan't to create with extra controls they buy. Despite not being a control developer (like you), this kind of solution never ever crossed my mind: it's violating dry. Also creating a wrapper control (via directive) is an overkill (to push down all inputs, re-bind all events).
I'd go into a solution via extra directive, but the proper X placing (and on-click event listening) is heavily KENDO CSS dependent and a proper way to place it is needed in all cases (sizes - px, em, rem, %, ...). But if that small part would be shown in those samples, rest would be easy to go and a 100% success (for a long term).
Beside of whether the above is something we developer get, considering an empty selection (and allowing users to clear a selection easily) is IMHO a grounded request. You got it on comboboxes too, right? And dropdowns and comboboxes differ mainly (just) in the way of filtering...
Hello @hidegh
The default item and the placeholder are by no means equivalent.
The placeholder attribute in it's nature is just a plain text that hints what the expected user input is. That is why placeholders are typically seen in empty components that expect user input, such as AutoComplete, ComboBox, MultiSelect, DateInput and so on.
The DropDownList's default item on the other hand is, as the name suggests, an item. While its text could, and often is used as a hint, the item also has a value. The most common scenario is to use a default item with a value of undefined, which has two benefits. First, it gets automatically selected and displayed after initializing the component. And second - it allows the users to easily clear the component's value by select the default item. This, aside from the cluttered UI, also is the reason why we currently do not provide a dedicated "clear value" button. I would however, encourage you to submit this and the placeholder as a feature requests on our feedback portal.
I hope this clears the distinction between the two, why the DropDownList currently does not have a placeholder attribute and why the default item behaves the way it does.
Furthermore, I'd like to mention the existence of the TextBoxContainerComponent, which could be used to add a floating label. This closely resembles a placeholder in Angular Material.
Let me get to the other points you mentioned:
At this point both the selection and the focus remain on the selected item (if exist in the filtered data set), regardless of whether it's an actual item or the default one. After discussing this behavior, we decided to move the focus to the first item after the default one. Bypassing the keyboard and selection events is currently not supported out of the box, however you could tap into the SelectionService's events.
Creating a wrapper component or a directive is a rather common case when reusing a customized component is necessary. Adding an element to the DOM and listening to its click event is hardly an overkill. Here's a simple proof of concept example of how adding a clear button could be done. As mentioned above, we would welcome a feature request through the feedback portal. This would help us prioritize the feature based on how popular the request is.
The fixes are included in the dev build of the @progress/kendo-angular-dropdowns package v3.4.0-dev.201811091501.
defaultItem is now selectable after filtering;An example with the corrected behavior can be seen here. The sample project uses the dev version of the dropdowns package.
Awesome. Tx.
Also based on the responses and samples (with some minor alteration and with 1 internal method call) I managed to create a generic (no-code) clear function that should make dropdownlist behave as combobox when clearing. Samlpe (temporary) here, a cleaned up code below.
import { Component, Directive, Renderer2, AfterViewInit, OnDestroy, ViewChild } from '@angular/core';
import { DropDownListComponent } from '@progress/kendo-angular-dropdowns';
import { Subscription } from 'rxjs/Subscription';
import { take } from 'rxjs/operators/take';
/*
Adds a clear button to all drop-down lists!
Original implementation used an Output property (event) so for the clearing a view-method was responsible.
See: https://stackblitz.com/edit/angular-uv553z-objyev?file=app/app.component.ts
This version behaves same as the combo-box or autocomplete (so sets a undefined value).
*/
@Directive({
selector: 'kendo-dropdownlist'
})
export class DropDownListClearButtonDirective implements AfterViewInit, OnDestroy {
public resetButton: HTMLElement;
private changeSubscription: Subscription;
constructor(
public renderer: Renderer2,
public ddl: DropDownListComponent) {
this.changeSubscription = this.ddl.valueChange.subscribe(() => { this.toggle(!!this.ddl.value) });
}
private toggle(visible: boolean): void {
this.renderer.setStyle(this.resetButton, "visibility", visible ? "visible" : "hidden");
}
private reset(): void {
this.ddl.open.pipe(take(1)).subscribe((e: any) => { e.preventDefault(); });
// does the desired clean, but without UI update and events...
this.ddl.reset();
// update UI
this.ddl.writeValue(this.ddl.value);
// NOTE: emit change does the same as the 2 lines below - (<any>this.ddl).emitChange(undefined);
(<any>this.ddl).onChangeCallback(this.ddl.value);
this.ddl.valueChange.emit(this.ddl.value);
this.toggle(false);
}
public ngAfterViewInit(): void {
const openButton = this.ddl.wrapper.nativeElement.querySelector(".k-select");
this.resetButton = document.createElement('span');
this.resetButton.setAttribute('class', 'k-select');
this.resetButton.innerHTML = "<span class='k-icon k-i-close'></span>";
this.renderer.insertBefore(this.ddl.wrapper.nativeElement, this.resetButton, openButton);
this.renderer.listen(this.resetButton, "click", this.reset.bind(this));
this.toggle(false);
}
public ngOnDestroy(): void {
this.changeSubscription.unsubscribe();
}
}
Most helpful comment
The fixes are included in the dev build of the
@progress/kendo-angular-dropdownspackage v3.4.0-dev.201811091501.defaultItemis now selectable after filtering;An example with the corrected behavior can be seen here. The sample project uses the
devversion of the dropdowns package.