File tree 4 files changed +80
-6
lines changed
4 files changed +80
-6
lines changed Original file line number Diff line number Diff line change @@ -53,6 +53,24 @@ export const Validation = {
53
53
} ,
54
54
} ;
55
55
56
+ export const ExtraProps = {
57
+ name : 'Customized options text' ,
58
+ render : Basic . render ,
59
+ args : {
60
+ ...Basic . args ,
61
+ label : 'This implementation uses the "optionTextFn" and "menuProps"' ,
62
+ options : [
63
+ { value : 'AR' , label : 'Argentina' } ,
64
+ { value : 'AD' , label : 'Andorra' } ,
65
+ { value : 'PL' , label : 'Poland' } ,
66
+ ] ,
67
+ propValue : 'value' ,
68
+ propText : 'label' ,
69
+ optionTextFn : ( item ) => `${ item . label } (${ item . value } )` ,
70
+ menuProps : { fullWidth : false } ,
71
+ } ,
72
+ } ;
73
+
56
74
export default {
57
75
title : 'Components/Autocomplete' ,
58
76
component : Autocomplete ,
Original file line number Diff line number Diff line change 9
9
:propValue =" propValue"
10
10
:rules =" rules"
11
11
:hint =" hint"
12
+ :optionTextFn =" optionTextFn"
13
+ :menuProps =" menuProps"
12
14
@value-change =" updateSelected"
13
15
>
14
16
<div
15
17
slot =" search-input"
16
18
class =" autocomplete__search"
19
+ :class =" { 'cancel-left-padding': !selected }"
17
20
>
18
21
<ui-textfield
19
22
:value =" userInput"
@@ -65,10 +68,25 @@ const props = defineProps({
65
68
type: String ,
66
69
default: ' ' ,
67
70
},
71
+ optionTextFn: {
72
+ type: Function ,
73
+ default: null ,
74
+ },
75
+ menuProps: {
76
+ type: Object ,
77
+ default : () => ({
78
+ fullWidth: true ,
79
+ }),
80
+ },
68
81
});
69
82
83
+ const emit = defineEmits ([' valueChange' ]);
84
+
70
85
let userInput = ref (' ' );
71
- let selected = ref (' ' );
86
+ let selected = defineModel ({
87
+ type: String ,
88
+ required: true ,
89
+ });
72
90
73
91
const getOptionText = (option ) => (typeof option === ' object' ? option[props .propText ] : option);
74
92
@@ -89,6 +107,7 @@ const onUserInput = (e) => {
89
107
const updateSelected = (e ) => {
90
108
selected .value = e .detail [0 ];
91
109
userInput .value = ' ' ;
110
+ emit (' valueChange' , selected .value );
92
111
};
93
112
</script >
94
113
@@ -97,9 +116,6 @@ const updateSelected = (e) => {
97
116
98
117
& __search {
99
118
color : inherit ;
100
- -webkit- appearance : none ;
101
- -moz- appearance : none ;
102
- appearance : none ;
103
119
line-height : 20px ;
104
120
font-size : 14px ;
105
121
border : 1px solid transparent ;
@@ -111,7 +127,11 @@ const updateSelected = (e) => {
111
127
width : 0 ;
112
128
max-width : 100% ;
113
129
flex-grow : 1 ;
114
- z-index : 1 ;
130
+ }
131
+
132
+ // there is too much padding coming from select + textfield
133
+ .cancel-left-padding {
134
+ margin-left : - 11px ;
115
135
}
116
136
}
117
137
</style >
Original file line number Diff line number Diff line change 1
1
import { mount } from '@vue/test-utils' ;
2
2
import Select from './widget.vue' ;
3
+ import { nextTick } from 'vue' ;
3
4
4
5
describe ( 'Select' , ( ) => {
5
6
let wrapper ;
@@ -154,4 +155,29 @@ describe('Select', () => {
154
155
} ) ;
155
156
} ) ;
156
157
} ) ;
158
+
159
+ describe ( 'watch' , ( ) => {
160
+ beforeEach ( ( ) => {
161
+ wrapper = mount ( Select , {
162
+ props : {
163
+ modelValue : '1' ,
164
+ options : [
165
+ { id : '1' , value : 'Option 1' } ,
166
+ { id : '2' , value : 'Option 2' } ,
167
+ ] ,
168
+ propValue : 'id' ,
169
+ } ,
170
+ } ) ;
171
+ } ) ;
172
+
173
+ it ( 'should update selectedOption when model changes' , async ( ) => {
174
+ // Initial check
175
+ expect ( wrapper . vm . selectedOption ) . toEqual ( { id : '1' , value : 'Option 1' } ) ;
176
+
177
+ await wrapper . setProps ( { modelValue : '2' } ) ;
178
+ await nextTick ( ) ;
179
+
180
+ expect ( wrapper . vm . selectedOption ) . toEqual ( { id : '2' , value : 'Option 2' } ) ;
181
+ } ) ;
182
+ } ) ;
157
183
} ) ;
Original file line number Diff line number Diff line change 73
73
</template >
74
74
75
75
<script setup>
76
- import { computed , ref } from ' vue' ;
76
+ import { computed , ref , watch } from ' vue' ;
77
77
import Menu from ' ~widgets/menu/widget.vue' ;
78
78
import Icon from ' ~widgets/icon/widget.vue' ;
79
79
import { useFieldValidation } from ' ~composables/validation' ;
@@ -168,6 +168,16 @@ const getDisplayText = (item) => {
168
168
if (props .optionTextFn ) return props .optionTextFn (item);
169
169
return item[props .propText ];
170
170
};
171
+
172
+ watch (
173
+ model,
174
+ (newValue ) => {
175
+ selectedOption .value = computedOptions .value .find (
176
+ (option ) => option[props .propValue ] === newValue,
177
+ );
178
+ },
179
+ { immediate: true },
180
+ );
171
181
</script >
172
182
173
183
<style lang="stylus" scoped>
You can’t perform that action at this time.
0 commit comments