Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core/select): show info if no matches found and fix selection bug #489

Merged
merged 6 commits into from
Apr 21, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/angular/src/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1348,14 +1348,14 @@ export declare interface IxPill extends Components.IxPill {}


@ProxyCmp({
inputs: ['allowClear', 'disabled', 'editable', 'hideListHeader', 'i18nPlaceholder', 'i18nPlaceholderEditable', 'i18nSelectListHeader', 'mode', 'readonly', 'selectedIndices']
inputs: ['allowClear', 'disabled', 'editable', 'hideListHeader', 'i18nNoMatches', 'i18nPlaceholder', 'i18nPlaceholderEditable', 'i18nSelectListHeader', 'mode', 'readonly', 'selectedIndices']
})
@Component({
selector: 'ix-select',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['allowClear', 'disabled', 'editable', 'hideListHeader', 'i18nPlaceholder', 'i18nPlaceholderEditable', 'i18nSelectListHeader', 'mode', 'readonly', 'selectedIndices'],
inputs: ['allowClear', 'disabled', 'editable', 'hideListHeader', 'i18nNoMatches', 'i18nPlaceholder', 'i18nPlaceholderEditable', 'i18nSelectListHeader', 'mode', 'readonly', 'selectedIndices'],
})
export class IxSelect {
protected el: HTMLElement;
Expand Down
19 changes: 18 additions & 1 deletion packages/core/component-doc.json
Original file line number Diff line number Diff line change
Expand Up @@ -7059,6 +7059,23 @@
"optional": false,
"required": false
},
{
"name": "i18nNoMatches",
"type": "string",
"mutable": false,
"attr": "i-1-8n-no-matches",
"reflectToAttr": false,
"docs": "Hint inside of dropdown if no items where found with current filter text",
"docsTags": [],
"default": "'No matches'",
"values": [
{
"type": "string"
}
],
"optional": false,
"required": false
},
{
"name": "i18nPlaceholder",
"type": "string",
Expand Down Expand Up @@ -7155,7 +7172,7 @@
"mutable": true,
"attr": "selected-indices",
"reflectToAttr": false,
"docs": "Indices of selected items",
"docs": "Indices of selected items\nThis corresponds to the value property of ix-select-items and therefor not neccessarily the indices of the items in the list.",
"docsTags": [],
"default": "[]",
"values": [
Expand Down
12 changes: 10 additions & 2 deletions packages/core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1222,6 +1222,10 @@ export namespace Components {
* @
*/
"hideListHeader": boolean;
/**
* Hint inside of dropdown if no items where found with current filter text
*/
"i18nNoMatches": string;
/**
* Input field placeholder
*/
Expand All @@ -1243,7 +1247,7 @@ export namespace Components {
*/
"readonly": boolean;
/**
* Indices of selected items
* Indices of selected items This corresponds to the value property of ix-select-items and therefor not neccessarily the indices of the items in the list.
*/
"selectedIndices": string | string[];
}
Expand Down Expand Up @@ -3661,6 +3665,10 @@ declare namespace LocalJSX {
* @
*/
"hideListHeader"?: boolean;
/**
* Hint inside of dropdown if no items where found with current filter text
*/
"i18nNoMatches"?: string;
/**
* Input field placeholder
*/
Expand Down Expand Up @@ -3690,7 +3698,7 @@ declare namespace LocalJSX {
*/
"readonly"?: boolean;
/**
* Indices of selected items
* Indices of selected items This corresponds to the value property of ix-select-items and therefor not neccessarily the indices of the items in the list.
*/
"selectedIndices"?: string | string[];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

:host {
display: block;
min-width: 10rem;

&.icon-only {
min-width: 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export class DropdownItem {
disabled: this.disabled,
}}
onClick={() => this.emitItemClick()}
tabindex={0}
>
{this.checked ? (
<ix-icon class="checkmark" name="single-check" size="16"></ix-icon>
Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/components/dropdown/dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,10 @@ export class Dropdown {
}

if (this.placement.includes('auto') || isSubmenu) {
positionConfig.middleware.push(flip());
positionConfig.middleware.push(
flip({ fallbackStrategy: 'initialPlacement' })
);
positionConfig.placement = 'bottom-start';
} else {
positionConfig.placement = this.placement as
| BasePlacement
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/components/pagination/pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ export class Pagination {
<span class="item-count">
{this.i18nItems}
<ix-select
hideListHeader
i18nPlaceholder=""
i18nSelectListHeader=""
selected-indices={this.itemCount}
Expand Down
6 changes: 0 additions & 6 deletions packages/core/src/components/select-item/select-item.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,4 @@

:host {
display: block;

ix-dropdown-item {
button {
margin-left: 1rem;
}
}
}
1 change: 0 additions & 1 deletion packages/core/src/components/select-item/select-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ export class SelectItem {
<Host>
<ix-dropdown-item
checked={this.selected}
hover={this.hover}
label={this.label ? this.label : this.value}
onItemClick={(e) => this.onItemClick(e)}
></ix-dropdown-item>
Expand Down
82 changes: 52 additions & 30 deletions packages/core/src/components/select/select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export class Select {

/**
* Indices of selected items
* This corresponds to the value property of ix-select-items and therefor not neccessarily the indices of the items in the list.
*/
@Prop({ mutable: true }) selectedIndices: string | string[] = [];

Expand Down Expand Up @@ -74,6 +75,11 @@ export class Select {
*/
@Prop() i18nSelectListHeader = 'Please select an option';

/**
* Hint inside of dropdown if no items where found with current filter text
*/
@Prop() i18nNoMatches = 'No matches';
nuke-ellington marked this conversation as resolved.
Show resolved Hide resolved

/**
* Hide list header
*
Expand Down Expand Up @@ -128,6 +134,10 @@ export class Select {
return this.mode === 'multiple';
}

get isEveryDropdownItemHidden() {
return this.items.every((item) => item.classList.contains('d-none'));
}

@Watch('selectedIndices')
watchSelectedIndices(newId: string | string[]) {
if (!newId) {
Expand All @@ -149,17 +159,6 @@ export class Select {
this.emitItemClick(newId);
}

@Watch('inputFilterText')
watchInputText(newValue: string) {
if (!this.editable) {
return;
}

if (this.itemExists(newValue)) {
return;
}
}

private emitItemClick(newId: string) {
if (this.isMultipleMode && Array.isArray(this.selectedIndices)) {
if (this.selectedIndices.includes(newId)) {
Expand All @@ -180,11 +179,11 @@ export class Select {
return;
}

const test = document.createElement('ix-select-item');
test.value = value;
test.label = value;
const newItem = document.createElement('ix-select-item');
newItem.value = value;
newItem.label = value;

this.addItemRef.appendChild(test);
this.addItemRef.appendChild(newItem);

this.clearInput();
this.emitItemClick(value);
Expand Down Expand Up @@ -239,16 +238,17 @@ export class Select {

private dropdownVisibilityChanged(event: CustomEvent<boolean>) {
this.dropdownShow = event.detail;
this.hasFocus = event.detail;

if (event.detail) {
this.inputRef.focus();
this.inputRef.select();

this.navigationItem = this.items[0];
this.setHoverEffectForNavigatedSelectItem();
this.removeHiddenFromItems();
this.isDropdownEmpty = this.isEveryDropdownItemHidden;
} else {
this.navigationItem = undefined;
}
this.hasFocus = event.detail;
}

@Listen('keydown', {
Expand Down Expand Up @@ -294,6 +294,11 @@ export class Select {
event.stopPropagation();
event.preventDefault();

const focusItem = this.items.find(
(item) => document.activeElement === item.querySelector('button')
);
this.navigationItem = focusItem;

const selectItems = this.items.filter(
(i) => !i.classList.contains('d-none')
);
Expand All @@ -310,13 +315,12 @@ export class Select {
}

private setHoverEffectForNavigatedSelectItem() {
this.items.forEach((item: HTMLIxSelectItemElement) => {
item.hover = item === this.navigationItem;
});
this.navigationItem?.querySelector('button').focus();
}

private filterItemsWithTypeahead() {
this.inputFilterText = this.inputRef.value;

if (this.inputFilterText) {
this.items.forEach((item) => {
item.classList.remove('d-none');
Expand All @@ -329,9 +333,8 @@ export class Select {
} else {
this.removeHiddenFromItems();
}
this.isDropdownEmpty = this.items.every((item) =>
item.classList.contains('d-none')
);

this.isDropdownEmpty = this.isEveryDropdownItemHidden;
}

private removeHiddenFromItems() {
Expand All @@ -353,6 +356,22 @@ export class Select {
this.dropdownShow = false;
}

private onInputBlur(e) {
if (this.editable) {
return;
}

if (this.isSingleMode) {
if (this.dropdownShow && this.isDropdownEmpty) {
this.dropdownShow = false;
}
}

if (!this.dropdownShow && this.mode !== 'multiple') {
e.target['value'] = this.value;
}
}

private placeholderValue() {
if (this.editable) {
return this.i18nPlaceholderEditable;
Expand Down Expand Up @@ -411,6 +430,7 @@ export class Select {
placeholder={this.placeholderValue()}
value={this.inputValue}
ref={(ref) => (this.inputRef = ref)}
onBlur={(e) => this.onInputBlur(e)}
onInput={() => this.filterItemsWithTypeahead()}
/>
{this.allowClear &&
Expand Down Expand Up @@ -446,25 +466,22 @@ export class Select {
ref={(ref) => (this.dropdownRef = ref)}
show={this.dropdownShow}
class={{
'd-none':
this.disabled ||
this.readonly ||
(this.isDropdownEmpty && !this.editable),
'd-none': this.disabled || this.readonly,
}}
anchor={this.dropdownAnchor}
trigger={this.dropdownWrapperRef}
onShowChanged={(e) => this.dropdownVisibilityChanged(e)}
placement="auto-start"
overwriteDropdownStyle={async () => {
return {
width: `${this.hostElement.clientWidth}px`,
minWidth: `${this.hostElement.clientWidth}px`,
};
}}
>
<div
class={{
'select-list-header': true,
hidden: this.hideListHeader === true,
hidden: this.hideListHeader || this.isDropdownEmpty,
}}
title={this.i18nSelectListHeader}
>
Expand All @@ -490,6 +507,11 @@ export class Select {
}}
></ix-dropdown-item>
)}
{this.isDropdownEmpty && !this.editable ? (
<div class="select-list-header">{this.i18nNoMatches}</div>
) : (
''
)}
</ix-dropdown>
</Host>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ regressionTest.describe('basic', () => {

await page.waitForSelector('.dropdown.show');

expect(await page.screenshot({ fullPage: true })).toMatchSnapshot();
expect(await page.screenshot({ fullPage: true })).toMatchSnapshot({
maxDiffPixelRatio: 0.01,
});
});
});
1 change: 1 addition & 0 deletions packages/vue/src/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,7 @@ export const IxSelect = /*@__PURE__*/ defineContainer<JSX.IxSelect>('ix-select',
'i18nPlaceholder',
'i18nPlaceholderEditable',
'i18nSelectListHeader',
'i18nNoMatches',
'hideListHeader',
'itemSelectionChange',
'addItem'
Expand Down