Skip to content

Commit d40d5fc

Browse files
committed
feat: Add "clear-value" prop for clearable behavior quasarframework#1157
1 parent 1f32b83 commit d40d5fc

File tree

10 files changed

+118
-264
lines changed

10 files changed

+118
-264
lines changed

src/components/autocomplete/QAutocomplete.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,9 @@ export default {
197197
case 27: // escape
198198
this.__clearSearch()
199199
break
200+
case 9: // tab
201+
this.hide()
202+
break
200203
}
201204
},
202205
__moveCursor (offset, e) {

src/components/color/QColor.js

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import QColorPicker from './QColorPicker'
66
import { QBtn } from '../btn'
77
import { QModal } from '../modal'
88
import clone from '../../utils/clone'
9-
import { stopAndPrevent } from '../../utils/event'
109

1110
const contentCss = __THEME__ === 'ios'
1211
? {
@@ -90,11 +89,6 @@ export default {
9089
this.focused = false
9190
return this.$refs.popup.hide()
9291
},
93-
clear (evt) {
94-
stopAndPrevent(evt)
95-
this.$emit('input', null)
96-
this.$emit('change', null)
97-
},
9892

9993
__onFocus () {
10094
this.__setModel(this.value)

src/components/datetime/QDatetime.js

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,6 @@ export default {
8787
this.focused = false
8888
return this.$refs.popup.hide()
8989
},
90-
clear (evt) {
91-
stopAndPrevent(evt)
92-
this.$emit('input', '')
93-
this.$emit('change', '')
94-
},
9590

9691
__onFocus () {
9792
if (this.defaultView) {

src/components/input/QInput.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,9 @@ export default {
242242
clearTimeout(this.timer)
243243
this.focus()
244244
if (this.editable) {
245-
this.model = this.isNumber ? null : ''
245+
this.model = this.clearValue || (this.isNumber ? null : '')
246246
this.$emit('input', this.model)
247+
this.$emit('clear')
247248
}
248249
},
249250

src/components/search/QSearch.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ export default {
7676
methods: {
7777
clear () {
7878
this.$refs.input.clear()
79+
this.$emit('clear')
7980
}
8081
},
8182
render (h) {
@@ -101,15 +102,17 @@ export default {
101102
maxLength: this.maxLength,
102103
color: this.color,
103104
before: this.controlBefore,
104-
after: this.controlAfter
105+
after: this.controlAfter,
106+
clearValue: this.clearValue
105107
},
106108
on: {
107109
input: v => { this.model = v },
108110
focus: this.__onFocus,
109111
blur: this.__onBlur,
110112
keyup: this.__onKeyup,
111113
keydown: this.__onKeydown,
112-
click: this.__onClick
114+
click: this.__onClick,
115+
clear: () => { this.$emit('clear') }
113116
}
114117
}, [
115118
this.$slots.default

src/components/select/QDialogSelect.vue

Lines changed: 0 additions & 138 deletions
This file was deleted.

src/components/select/QSelect.vue

Lines changed: 96 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,10 @@ import { QList, QItemWrapper } from '../list'
152152
import { QCheckbox } from '../checkbox'
153153
import { QRadio } from '../radio'
154154
import { QToggle } from '../toggle'
155-
import SelectMixin from '../../mixins/select'
155+
import { QIcon } from '../components/icon'
156+
import { QInputFrame } from '../components/input-frame'
157+
import { QChip } from '../components/chip'
158+
import FrameMixin from './input-frame'
156159
import extend from '../../utils/extend'
157160
158161
function defaultFilterFn (terms, obj) {
@@ -161,7 +164,7 @@ function defaultFilterFn (terms, obj) {
161164
162165
export default {
163166
name: 'q-select',
164-
mixins: [SelectMixin],
167+
mixins: [FrameMixin],
165168
components: {
166169
QFieldReset,
167170
QSearch,
@@ -170,15 +173,47 @@ export default {
170173
QItemWrapper,
171174
QCheckbox,
172175
QRadio,
173-
QToggle
176+
QToggle,
177+
QIcon,
178+
QInputFrame,
179+
QChip
174180
},
175181
props: {
176182
filter: [Function, Boolean],
177183
filterPlaceholder: String,
178184
autofocusFilter: Boolean,
179185
radio: Boolean,
180186
placeholder: String,
181-
separator: Boolean
187+
separator: Boolean,
188+
value: { required: true },
189+
multiple: Boolean,
190+
toggle: Boolean,
191+
chips: Boolean,
192+
options: {
193+
type: Array,
194+
required: true,
195+
validator: v => v.every(o => 'label' in o && 'value' in o)
196+
},
197+
frameColor: String,
198+
displayValue: String,
199+
clearable: Boolean,
200+
clearValue: {}
201+
},
202+
data () {
203+
return {
204+
model: this.multiple && Array.isArray(this.value)
205+
? this.value.slice()
206+
: this.value,
207+
terms: '',
208+
focused: false
209+
}
210+
},
211+
watch: {
212+
value (val) {
213+
this.model = this.multiple && Array.isArray(val)
214+
? val.slice()
215+
: val
216+
}
182217
},
183218
computed: {
184219
optModel () {
@@ -205,6 +240,36 @@ export default {
205240
return this.multiple
206241
? `.q-item-side > ${this.toggle ? '.q-toggle' : '.q-checkbox'} > .active`
207242
: `.q-item.active`
243+
},
244+
actualValue () {
245+
if (this.displayValue) {
246+
return this.displayValue
247+
}
248+
if (!this.multiple) {
249+
const opt = this.options.find(opt => opt.value === this.model)
250+
return opt ? opt.label : ''
251+
}
252+
253+
const opt = this.selectedOptions.map(opt => opt.label)
254+
return opt.length ? opt.join(', ') : ''
255+
},
256+
selectedOptions () {
257+
if (this.multiple) {
258+
return this.length > 0
259+
? this.options.filter(opt => this.model.includes(opt.value))
260+
: []
261+
}
262+
},
263+
hasChips () {
264+
return this.multiple && this.chips
265+
},
266+
length () {
267+
return this.multiple
268+
? this.model.length
269+
: ([null, undefined, ''].includes(this.model) ? 0 : 1)
270+
},
271+
additionalLength () {
272+
return this.displayValue && this.displayValue.length > 0
208273
}
209274
},
210275
methods: {
@@ -256,6 +321,33 @@ export default {
256321
}
257322
this.__emit(val)
258323
this.hide()
324+
},
325+
__toggleMultiple (value, disable) {
326+
if (disable) {
327+
return
328+
}
329+
const
330+
model = this.model,
331+
index = model.indexOf(value)
332+
333+
if (index > -1) {
334+
model.splice(index, 1)
335+
}
336+
else {
337+
model.push(value)
338+
}
339+
340+
this.$emit('input', model)
341+
},
342+
__emit (val) {
343+
if (this.value !== val) {
344+
this.$emit('input', val)
345+
}
346+
this.$emit('change', val)
347+
},
348+
clear () {
349+
this.__emit(this.clearValue || (this.multiple ? [] : null))
350+
this.$emit('clear')
259351
}
260352
}
261353
}

src/mixins/input.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
import { stopAndPrevent } from '../../utils/event'
2+
13
export default {
24
props: {
35
autofocus: [Boolean, String],
46
name: String,
57
maxLength: [Number, String],
68
maxHeight: Number,
79
placeholder: String,
8-
loading: Boolean
10+
loading: Boolean,
11+
clearValue: {}
912
},
1013
data () {
1114
return {
@@ -33,6 +36,13 @@ export default {
3336
select () {
3437
this.$refs.input.select()
3538
},
39+
clear (evt) {
40+
stopAndPrevent(evt)
41+
const val = this.clearValue || null
42+
this.$emit('input', val)
43+
this.$emit('change', val)
44+
this.$emit('clear')
45+
},
3646

3747
__onFocus (e) {
3848
clearTimeout(this.timer)

0 commit comments

Comments
 (0)