Skip to content

Commit

Permalink
Fixed #2902 - Add selectOnFocus property to Overlay components
Browse files Browse the repository at this point in the history
  • Loading branch information
mertsincan committed Aug 30, 2022
1 parent 7bdbeec commit c391fa4
Show file tree
Hide file tree
Showing 16 changed files with 111 additions and 28 deletions.
6 changes: 6 additions & 0 deletions api-generator/components/autocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ const AutoCompleteProps = [
default: "true",
description: "Whether to focus on the first visible or selected element when the overlay panel is shown."
},
{
name: "selectOnFocus",
type: "boolean",
default: "false",
description: "When enabled, the focused option is selected."
},
{
name: "searchLocale",
type: "string",
Expand Down
6 changes: 6 additions & 0 deletions api-generator/components/cascadeselect.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ const CascadeSelectProps = [
default: "true",
description: "Whether to focus on the first visible or selected element when the overlay panel is shown."
},
{
name: "selectOnFocus",
type: "boolean",
default: "false",
description: "When enabled, the focused option is selected/opened."
},
{
name: "searchLocale",
type: "string",
Expand Down
6 changes: 6 additions & 0 deletions api-generator/components/dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,12 @@ const DropdownProps = [
default: "true",
description: "Whether to focus on the first visible or selected element when the overlay panel is shown."
},
{
name: "selectOnFocus",
type: "boolean",
default: "false",
description: "When enabled, the focused option is selected."
},
{
name: "filterMessage",
type: "string",
Expand Down
6 changes: 6 additions & 0 deletions api-generator/components/listbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ const ListboxProps = [
default: "true",
description: "Whether to focus on the first visible or selected element."
},
{
name: "selectOnFocus",
type: "boolean",
default: "false",
description: "When enabled, the focused option is selected."
},
{
name: "filterMessage",
type: "string",
Expand Down
5 changes: 5 additions & 0 deletions src/components/autocomplete/AutoComplete.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,11 @@ export interface AutoCompleteProps {
* Default value is true.
*/
autoOptionFocus?: boolean | undefined;
/**
* When enabled, the focused option is selected.
* Default value is false.
*/
selectOnFocus?: boolean | undefined;
/**
* Locale to use in searching. The default locale is the host environment's current locale.
*/
Expand Down
16 changes: 9 additions & 7 deletions src/components/autocomplete/AutoComplete.vue
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export default {
type: String,
default: 'blank'
},
autoHighlight: { // TODO: Deprecated since v3.16.0
autoHighlight: { // TODO: Deprecated since v3.16.0. Use selectOnFocus property instead.
type: Boolean,
default: false
},
Expand Down Expand Up @@ -154,6 +154,10 @@ export default {
type: Boolean,
default: true
},
selectOnFocus: {
type: Boolean,
default: false
},
searchLocale: {
type: String,
default: undefined
Expand Down Expand Up @@ -193,7 +197,6 @@ export default {
overlay: null,
virtualScroller: null,
searchTimeout: null,
selectOnFocus: false,
focusOnHover: false,
dirty: false,
data() {
Expand Down Expand Up @@ -464,7 +467,7 @@ export default {
this.$emit('dropdown-click', { originalEvent: event, query });
},
onOptionSelect(event, option) {
onOptionSelect(event, option, isHide = true) {
const value = this.getOptionValue(option);
if (this.multiple) {
Expand All @@ -480,7 +483,7 @@ export default {
this.$emit('item-select', { originalEvent: event, value: option });
this.hide(true);
isHide && this.hide(true);
},
onOptionMouseMove(event, index) {
if (this.focusOnHover) {
Expand Down Expand Up @@ -788,7 +791,7 @@ export default {
this.scrollInView();
if (this.selectOnFocus || this.autoHighlight) {
this.updateModel(event, this.getOptionValue(this.visibleOptions[index]));
this.onOptionSelect(event, this.visibleOptions[index], false);
}
}
},
Expand All @@ -807,8 +810,7 @@ export default {
autoUpdateModel() {
if ((this.selectOnFocus || this.autoHighlight) && this.autoOptionFocus && !this.hasSelectedOption) {
this.focusedOptionIndex = this.findFirstFocusedOptionIndex();
const value = this.getOptionValue(this.visibleOptions[this.focusedOptionIndex]);
this.updateModel(null, this.multiple ? [value] : value);
this.onOptionSelect(null, this.visibleOptions[this.focusedOptionIndex], false);
}
},
updateModel(event, value) {
Expand Down
5 changes: 5 additions & 0 deletions src/components/cascadeselect/CascadeSelect.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ export interface CascadeSelectProps {
* Default value is true.
*/
autoOptionFocus?: boolean | undefined;
/**
* When enabled, the focused option is selected/opened.
* Default value is false.
*/
selectOnFocus?: boolean | undefined;
/**
* Locale to use in searching. The default locale is the host environment's current locale.
*/
Expand Down
29 changes: 19 additions & 10 deletions src/components/cascadeselect/CascadeSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ export default {
type: Boolean,
default: true
},
selectOnFocus: {
type: Boolean,
default: false
},
searchLocale: {
type: String,
default: undefined
Expand Down Expand Up @@ -122,7 +126,6 @@ export default {
overlay: null,
searchTimeout: null,
searchValue: null,
selectOnFocus: false,
focusOnHover: false,
data() {
return {
Expand All @@ -141,6 +144,8 @@ export default {
},
mounted() {
this.id = this.$attrs.id || this.id;
this.autoUpdateModel();
},
beforeUnmount() {
this.unbindOutsideClickListener();
Expand Down Expand Up @@ -185,7 +190,7 @@ export default {
show(isFocus) {
this.$emit('before-show');
this.overlayVisible = true;
this.activeOptionPath = this.findOptionPathByValue(this.modelValue);
this.activeOptionPath = this.hasSelectedOption ? this.findOptionPathByValue(this.modelValue) : this.activeOptionPath;
if (this.hasSelectedOption && ObjectUtils.isNotEmpty(this.activeOptionPath)) {
const processedOption = this.activeOptionPath[this.activeOptionPath.length - 1];
Expand Down Expand Up @@ -286,7 +291,10 @@ export default {
}
},
onOptionChange(event) {
const { originalEvent, processedOption, isFocus } = event;
const { originalEvent, processedOption, isFocus, isHide } = event;
if (ObjectUtils.isEmpty(processedOption)) return;
const { index, level, parentKey, children } = processedOption;
const grouped = ObjectUtils.isNotEmpty(children);
Expand All @@ -296,15 +304,15 @@ export default {
this.focusedOptionInfo = { index, level, parentKey };
this.activeOptionPath = activeOptionPath;
grouped ? this.onOptionGroupSelect(originalEvent, processedOption) : this.onOptionSelect(originalEvent, processedOption);
grouped ? this.onOptionGroupSelect(originalEvent, processedOption) : this.onOptionSelect(originalEvent, processedOption, isHide);
isFocus && this.$refs.focusInput.focus();
},
onOptionSelect(event, processedOption) {
onOptionSelect(event, processedOption, isHide = true) {
const value = this.getOptionValue(processedOption.option);
this.activeOptionPath.forEach(p => p.selected = true);
this.updateModel(event, value);
this.hide(true);
isHide && this.hide(true);
},
onOptionGroupSelect(event, processedOption) {
this.dirty = true;
Expand Down Expand Up @@ -634,7 +642,7 @@ export default {
this.scrollInView();
if (this.selectOnFocus) {
this.updateModel(event, this.getOptionValue(this.visibleOptions[index]));
this.onOptionChange({ originalEvent: event, processedOption: this.visibleOptions[index], isHide: false });
}
}
},
Expand All @@ -648,8 +656,9 @@ export default {
autoUpdateModel() {
if (this.selectOnFocus && this.autoOptionFocus && !this.hasSelectedOption) {
this.focusedOptionInfo.index = this.findFirstFocusedOptionIndex();
const value = this.getOptionValue(this.visibleOptions[this.focusedOptionInfo.index]);
this.updateModel(null, value);
this.onOptionChange({ processedOption: this.visibleOptions[this.focusedOptionInfo.index], isHide: false });
!this.overlayVisible && (this.focusedOptionInfo = { index: -1, level: 0, parentKey: '' });
}
},
updateModel(event, value) {
Expand Down Expand Up @@ -713,7 +722,7 @@ export default {
if (this.hasSelectedOption) {
const activeOptionPath = this.findOptionPathByValue(this.modelValue);
const processedOption = activeOptionPath.length ? activeOptionPath[activeOptionPath.length - 1] : null;
const processedOption = ObjectUtils.isNotEmpty(activeOptionPath) ? activeOptionPath[activeOptionPath.length - 1] : null;
return processedOption ? this.getOptionLabel(processedOption.option) : label;
}
Expand Down
5 changes: 5 additions & 0 deletions src/components/dropdown/Dropdown.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ export interface DropdownProps {
* Default value is true.
*/
autoOptionFocus?: boolean | undefined;
/**
* When enabled, the focused option is selected.
* Default value is false.
*/
selectOnFocus?: boolean | undefined;
/**
* Text to be displayed in hidden accessible field when filtering returns any results. Defaults to value from PrimeVue locale configuration.
* Default value is '{0} results are available'.
Expand Down
14 changes: 8 additions & 6 deletions src/components/dropdown/Dropdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ export default {
type: Boolean,
default: true
},
selectOnFocus: {
type: Boolean,
default: false
},
filterMessage: {
type: String,
default: null
Expand Down Expand Up @@ -182,7 +186,6 @@ export default {
searchTimeout: null,
searchValue: null,
isModelValueChanged: false,
selectOnFocus: false,
focusOnHover: false,
data() {
return {
Expand Down Expand Up @@ -391,11 +394,11 @@ export default {
onLastHiddenFocus() {
this.$refs.firstHiddenFocusableElementOnOverlay.focus();
},
onOptionSelect(event, option) {
onOptionSelect(event, option, isHide = true) {
const value = this.getOptionValue(option);
this.updateModel(event, value);
this.hide(true);
isHide && this.hide(true);
},
onOptionMouseMove(event, index) {
if (this.focusOnHover) {
Expand Down Expand Up @@ -744,7 +747,7 @@ export default {
this.scrollInView();
if (this.selectOnFocus) {
this.updateModel(event, this.getOptionValue(this.visibleOptions[index]));
this.onOptionSelect(event, this.visibleOptions[index], false);
}
}
},
Expand All @@ -763,8 +766,7 @@ export default {
autoUpdateModel() {
if (this.selectOnFocus && this.autoOptionFocus && !this.hasSelectedOption) {
this.focusedOptionIndex = this.findFirstFocusedOptionIndex();
const value = this.getOptionValue(this.visibleOptions[this.focusedOptionIndex]);
this.updateModel(null, value);
this.onOptionSelect(null, this.visibleOptions[this.focusedOptionIndex], false);
}
},
updateModel(event, value) {
Expand Down
5 changes: 5 additions & 0 deletions src/components/listbox/Listbox.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ export interface ListboxProps {
* Default value is true.
*/
autoOptionFocus?: boolean | undefined;
/**
* When enabled, the focused option is selected.
* Default value is false.
*/
selectOnFocus?: boolean | undefined;
/**
* Text to be displayed in hidden accessible field when filtering returns any results. Defaults to value from PrimeVue locale configuration.
* Default value is '{0} results are available'.
Expand Down
12 changes: 7 additions & 5 deletions src/components/listbox/Listbox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ export default {
type: Boolean,
default: true
},
selectOnFocus: {
type: Boolean,
default: false
},
filterMessage: {
type: String,
default: null
Expand Down Expand Up @@ -135,7 +139,6 @@ export default {
startRangeIndex: -1,
searchTimeout: null,
searchValue: '',
selectOnFocus: false,
focusOnHover: false,
data() {
return {
Expand Down Expand Up @@ -598,7 +601,7 @@ export default {
this.scrollInView();
if (this.selectOnFocus && !this.multiple) {
this.updateModel(event, this.getOptionValue(this.visibleOptions[index]));
this.onOptionSelect(event, this.visibleOptions[index]);
}
}
},
Expand All @@ -613,10 +616,9 @@ export default {
}
},
autoUpdateModel() {
if (this.selectOnFocus && this.autoOptionFocus && !this.hasSelectedOption) {
if (this.selectOnFocus && this.autoOptionFocus && !this.hasSelectedOption && !this.multiple) {
this.focusedOptionIndex = this.findFirstFocusedOptionIndex();
const value = this.getOptionValue(this.visibleOptions[this.focusedOptionIndex]);
this.updateModel(null, this.multiple ? [value] : value);
this.onOptionSelect(null, this.visibleOptions[this.focusedOptionIndex]);
}
},
updateModel(event, value) {
Expand Down
6 changes: 6 additions & 0 deletions src/views/autocomplete/AutoCompleteDoc.vue
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,12 @@ export default {
<td>true</td>
<td>Whether to focus on the first visible or selected element when the overlay panel is shown.</td>
</tr>
<tr>
<td>selectOnFocus</td>
<td>boolean</td>
<td>false</td>
<td>When enabled, the focused option is selected.</td>
</tr>
<tr>
<td>searchLocale</td>
<td>string</td>
Expand Down
6 changes: 6 additions & 0 deletions src/views/cascadeselect/CascadeSelectDoc.vue
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,12 @@ data() &#123;
<td>true</td>
<td>Whether to focus on the first visible or selected element when the overlay panel is shown.</td>
</tr>
<tr>
<td>selectOnFocus</td>
<td>boolean</td>
<td>false</td>
<td>When enabled, the focused option is selected/opened.</td>
</tr>
<tr>
<td>searchLocale</td>
<td>string</td>
Expand Down
6 changes: 6 additions & 0 deletions src/views/dropdown/DropdownDoc.vue
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,12 @@ export default {
<td>true</td>
<td>Whether to focus on the first visible or selected element when the overlay panel is shown.</td>
</tr>
<tr>
<td>selectOnFocus</td>
<td>boolean</td>
<td>false</td>
<td>When enabled, the focused option is selected.</td>
</tr>
<tr>
<td>filterMessage</td>
<td>string</td>
Expand Down
Loading

0 comments on commit c391fa4

Please sign in to comment.