@bildvitta/quasar-ui-asteroid 3.0.0-beta.9 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/QasAppBar.json +0 -4
- package/dist/api/QasBtn.json +2 -1
- package/dist/api/QasCard.json +13 -9
- package/dist/api/QasDateTimeInput.json +12 -12
- package/dist/api/QasDialog.json +6 -2
- package/dist/api/QasFilters.json +4 -4
- package/dist/api/QasFormGenerator.json +33 -2
- package/dist/api/QasFormView.json +26 -9
- package/dist/api/QasGridGenerator.json +5 -4
- package/dist/api/QasInput.json +1 -1
- package/dist/api/QasListItems.json +18 -17
- package/dist/api/QasListView.json +21 -7
- package/dist/api/QasNestedFields.json +13 -3
- package/dist/api/QasNumericInput.json +10 -10
- package/dist/api/QasPasswordInput.json +1 -1
- package/dist/api/QasSearchBox.json +80 -1
- package/dist/api/QasSelect.json +79 -6
- package/dist/api/QasSelectList.json +16 -14
- package/dist/api/QasSignaturePad.json +1 -1
- package/dist/api/QasSingleView.json +13 -4
- package/dist/api/QasTabsGenerator.json +5 -2
- package/dist/api/QasUploader.json +5 -0
- package/dist/asteroid.cjs.css +1 -1
- package/dist/asteroid.cjs.js +1463 -663
- package/dist/asteroid.cjs.min.js +2 -2
- package/dist/asteroid.esm.css +1 -1
- package/dist/asteroid.esm.js +1466 -666
- package/dist/asteroid.esm.min.js +2 -2
- package/dist/asteroid.umd.css +1 -1
- package/dist/asteroid.umd.js +1466 -667
- package/dist/asteroid.umd.min.js +2 -2
- package/dist/vetur/asteroid-attributes.json +162 -94
- package/dist/vetur/asteroid-tags.json +54 -37
- package/package.json +1 -1
- package/src/components/actions-menu/QasActionsMenu.vue +2 -8
- package/src/components/app-bar/QasAppBar.vue +16 -12
- package/src/components/app-bar/QasAppBar.yml +0 -4
- package/src/components/avatar/QasAvatar.vue +0 -4
- package/src/components/btn/QasBtn.vue +5 -8
- package/src/components/btn/QasBtn.yml +2 -1
- package/src/components/card/QasCard.vue +18 -9
- package/src/components/card/QasCard.yml +13 -9
- package/src/components/date-time-input/QasDateTimeInput.vue +39 -41
- package/src/components/date-time-input/QasDateTimeInput.yml +11 -12
- package/src/components/delete/QasDelete.vue +15 -1
- package/src/components/dialog/QasDialog.vue +26 -3
- package/src/components/dialog/QasDialog.yml +6 -3
- package/src/components/dialog-router/QasDialogRouter.vue +1 -1
- package/src/components/field/QasField.vue +15 -14
- package/src/components/filters/QasFilters.vue +27 -10
- package/src/components/filters/QasFilters.yml +4 -4
- package/src/components/form-generator/QasFormGenerator.vue +87 -12
- package/src/components/form-generator/QasFormGenerator.yml +16 -2
- package/src/components/form-view/QasFormView.vue +99 -39
- package/src/components/form-view/QasFormView.yml +22 -9
- package/src/components/grid-generator/QasGridGenerator.vue +23 -7
- package/src/components/grid-generator/QasGridGenerator.yml +5 -4
- package/src/components/input/QasInput.vue +37 -21
- package/src/components/input/QasInput.yml +1 -1
- package/src/components/layout/QasLayout.vue +4 -0
- package/src/components/list-items/QasListItems.vue +15 -23
- package/src/components/list-items/QasListItems.yml +14 -15
- package/src/components/list-view/QasListView.vue +45 -24
- package/src/components/list-view/QasListView.yml +19 -7
- package/src/components/map/QasMap.vue +5 -5
- package/src/components/nested-fields/QasNestedFields.vue +29 -21
- package/src/components/nested-fields/QasNestedFields.yml +9 -3
- package/src/components/numeric-input/QasNumericInput.vue +14 -14
- package/src/components/numeric-input/QasNumericInput.yml +10 -10
- package/src/components/page-header/QasPageHeader.vue +14 -11
- package/src/components/password-input/QasPasswordInput.vue +17 -16
- package/src/components/password-input/QasPasswordInput.yml +1 -1
- package/src/components/profile/QasProfile.vue +1 -1
- package/src/components/search-box/QasSearchBox.vue +137 -36
- package/src/components/search-box/QasSearchBox.yml +66 -1
- package/src/components/select/QasSelect.vue +62 -46
- package/src/components/select/QasSelect.yml +63 -6
- package/src/components/select-list/QasSelectList.vue +11 -27
- package/src/components/select-list/QasSelectList.yml +13 -14
- package/src/components/signature-pad/QasSignaturePad.yml +1 -1
- package/src/components/signature-uploader/QasSignatureUploader.vue +7 -5
- package/src/components/single-view/QasSingleView.vue +22 -6
- package/src/components/single-view/QasSingleView.yml +11 -4
- package/src/components/table-generator/QasTableGenerator.vue +11 -1
- package/src/components/tabs-generator/QasTabsGenerator.vue +2 -2
- package/src/components/tabs-generator/QasTabsGenerator.yml +2 -2
- package/src/components/text-truncate/QasTextTruncate.vue +1 -1
- package/src/components/uploader/QasUploader.vue +62 -15
- package/src/components/uploader/QasUploader.yml +5 -0
- package/src/helpers/camelize-fields-name.js +15 -0
- package/src/helpers/filters.js +2 -0
- package/src/helpers/get-normalized-options.js +20 -0
- package/src/helpers/handle-process.js +13 -0
- package/src/helpers/index.js +3 -0
- package/src/mixins/generator.js +10 -2
- package/src/mixins/index.js +2 -0
- package/src/mixins/search-filter.js +227 -0
- package/src/mixins/view.js +32 -12
- package/src/plugins/index.js +4 -2
- package/src/plugins/logger/Logger.js +44 -0
- package/src/plugins/logger/Logger.yml +9 -0
- package/src/vue-plugin.js +6 -3
|
@@ -1,42 +1,64 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<qas-box>
|
|
3
|
-
<
|
|
3
|
+
<qas-input v-bind="attributes" ref="search" v-model="mx_search">
|
|
4
4
|
<template #append>
|
|
5
5
|
<q-icon color="primary" name="o_search" />
|
|
6
6
|
</template>
|
|
7
|
-
</
|
|
7
|
+
</qas-input>
|
|
8
8
|
|
|
9
|
-
<div class="overflow-auto q-mt-xs relative-position" :style="
|
|
10
|
-
<
|
|
9
|
+
<div ref="scrollContainer" class="overflow-auto q-mt-xs relative-position" :style="containerStyle">
|
|
10
|
+
<component :is="component.is" v-bind="component.props">
|
|
11
|
+
<slot v-if="mx_hasFilteredOptions" />
|
|
12
|
+
</component>
|
|
11
13
|
|
|
12
|
-
<slot v-
|
|
14
|
+
<slot v-if="showSpinnerDots" name="loading">
|
|
15
|
+
<div class="flex justify-center q-pb-sm">
|
|
16
|
+
<q-spinner-dots color="primary" size="20px" />
|
|
17
|
+
</div>
|
|
18
|
+
</slot>
|
|
19
|
+
|
|
20
|
+
<slot v-if="showEmptyResult" name="empty-result">
|
|
13
21
|
<div class="absolute-center text-center">
|
|
14
22
|
<q-icon class="q-mb-sm text-center" color="primary" name="o_search" size="38px" />
|
|
15
|
-
<div>
|
|
23
|
+
<div>{{ emptyResultText }}</div>
|
|
16
24
|
</div>
|
|
17
25
|
</slot>
|
|
26
|
+
|
|
27
|
+
<q-inner-loading :showing="showInnerLoading">
|
|
28
|
+
<q-spinner color="grey" size="3em" />
|
|
29
|
+
</q-inner-loading>
|
|
18
30
|
</div>
|
|
19
31
|
</qas-box>
|
|
20
32
|
</template>
|
|
21
33
|
|
|
22
34
|
<script>
|
|
35
|
+
import { QInfiniteScroll } from 'quasar'
|
|
23
36
|
import Fuse from 'fuse.js'
|
|
24
37
|
|
|
25
38
|
import QasBox from '../box/QasBox.vue'
|
|
39
|
+
import { searchFilterMixin } from '../../mixins'
|
|
26
40
|
|
|
27
41
|
export default {
|
|
28
42
|
name: 'QasSearchBox',
|
|
29
43
|
|
|
30
44
|
components: {
|
|
31
|
-
QasBox
|
|
45
|
+
QasBox,
|
|
46
|
+
QInfiniteScroll
|
|
32
47
|
},
|
|
33
48
|
|
|
49
|
+
mixins: [searchFilterMixin],
|
|
50
|
+
|
|
34
51
|
props: {
|
|
35
52
|
emptyListHeight: {
|
|
36
53
|
default: '100px',
|
|
37
54
|
type: String
|
|
38
55
|
},
|
|
39
56
|
|
|
57
|
+
emptyResultText: {
|
|
58
|
+
default: 'Não há resultados disponíveis.',
|
|
59
|
+
type: String
|
|
60
|
+
},
|
|
61
|
+
|
|
40
62
|
fuseOptions: {
|
|
41
63
|
default: () => ({}),
|
|
42
64
|
type: Object
|
|
@@ -81,15 +103,52 @@ export default {
|
|
|
81
103
|
|
|
82
104
|
data () {
|
|
83
105
|
return {
|
|
84
|
-
fuse: null
|
|
85
|
-
searchResults: this.list,
|
|
86
|
-
search: ''
|
|
106
|
+
fuse: null
|
|
87
107
|
}
|
|
88
108
|
},
|
|
89
109
|
|
|
90
110
|
computed: {
|
|
91
|
-
|
|
92
|
-
return {
|
|
111
|
+
attributes () {
|
|
112
|
+
return {
|
|
113
|
+
clearable: true,
|
|
114
|
+
disable: this.isDisabled,
|
|
115
|
+
debounce: this.useLazyLoading ? 500 : 0,
|
|
116
|
+
outlined: true,
|
|
117
|
+
placeholder: this.placeholder,
|
|
118
|
+
hideBottomSpace: true,
|
|
119
|
+
error: this.mx_hasFetchError,
|
|
120
|
+
loading: this.mx_isFetching
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
containerStyle () {
|
|
125
|
+
return { height: this.containerHeight }
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
hasNoOptionsOnFirstFetch () {
|
|
129
|
+
return this.mx_fetchCount === 1 && !this.mx_hasFilteredOptions
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
containerHeight () {
|
|
133
|
+
const hasEmptyList = (!this.list.length && !this.useLazyLoading) || this.hasNoOptionsOnFirstFetch
|
|
134
|
+
|
|
135
|
+
return hasEmptyList ? this.emptyListHeight : this.height
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
component () {
|
|
139
|
+
const infiniteScrollProps = {
|
|
140
|
+
offset: 100,
|
|
141
|
+
scrollTarget: this.$refs.scrollContainer,
|
|
142
|
+
ref: 'infiniteScrollRef'
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
is: this.useLazyLoading ? 'q-infinite-scroll' : 'div',
|
|
147
|
+
props: {
|
|
148
|
+
...(this.useLazyLoading && infiniteScrollProps),
|
|
149
|
+
...(this.useLazyLoading && { onLoad: this.onInfiniteScroll })
|
|
150
|
+
}
|
|
151
|
+
}
|
|
93
152
|
},
|
|
94
153
|
|
|
95
154
|
defaultFuseOptions () {
|
|
@@ -101,63 +160,105 @@ export default {
|
|
|
101
160
|
}
|
|
102
161
|
},
|
|
103
162
|
|
|
104
|
-
|
|
105
|
-
return
|
|
163
|
+
isDisabled () {
|
|
164
|
+
return (!this.useLazyLoading && !this.list.length) || this.mx_isFetching || this.hasNoOptionsOnFirstFetch
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
showEmptyResult () {
|
|
168
|
+
return this.useEmptySlot && !this.mx_hasFilteredOptions && !this.mx_isFetching
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
showSpinnerDots () {
|
|
172
|
+
return this.mx_hasFilteredOptions && this.mx_isFetching
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
showInnerLoading () {
|
|
176
|
+
return !this.mx_hasFilteredOptions && this.mx_isFetching
|
|
106
177
|
}
|
|
107
178
|
},
|
|
108
179
|
|
|
109
180
|
watch: {
|
|
110
181
|
defaultFuseOptions (value) {
|
|
182
|
+
if (this.useLazyLoading) return
|
|
183
|
+
|
|
111
184
|
this.fuse.options = { ...this.fuse.options, ...value }
|
|
112
185
|
},
|
|
113
186
|
|
|
114
|
-
|
|
187
|
+
mx_hasFilteredOptions (value) {
|
|
115
188
|
!value && this.$emit('empty-result')
|
|
116
189
|
},
|
|
117
190
|
|
|
118
|
-
|
|
119
|
-
handler (value) {
|
|
120
|
-
this
|
|
191
|
+
mx_search: {
|
|
192
|
+
async handler (value) {
|
|
193
|
+
this.$emit('update:modelValue', value)
|
|
121
194
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
195
|
+
if (this.useLazyLoading) {
|
|
196
|
+
await this.mx_filterOptionsByStore(value)
|
|
197
|
+
|
|
198
|
+
this.$refs.infiniteScrollRef.resume()
|
|
199
|
+
this.$refs.search.focus()
|
|
200
|
+
|
|
201
|
+
return
|
|
202
|
+
}
|
|
125
203
|
|
|
126
|
-
|
|
204
|
+
this.filterOptionsByFuse(value)
|
|
205
|
+
}
|
|
127
206
|
},
|
|
128
207
|
|
|
129
|
-
|
|
208
|
+
modelValue: {
|
|
130
209
|
handler (value) {
|
|
131
|
-
this.
|
|
132
|
-
this.$emit('update:modelValue', value)
|
|
210
|
+
this.mx_search = value
|
|
133
211
|
},
|
|
134
212
|
|
|
135
213
|
immediate: true
|
|
136
214
|
},
|
|
137
215
|
|
|
138
|
-
|
|
139
|
-
handler (
|
|
140
|
-
this
|
|
216
|
+
mx_filteredOptions: {
|
|
217
|
+
handler (options) {
|
|
218
|
+
this.$emit('update:results', options)
|
|
141
219
|
},
|
|
220
|
+
|
|
142
221
|
immediate: true
|
|
143
222
|
}
|
|
144
223
|
},
|
|
145
224
|
|
|
146
225
|
created () {
|
|
147
|
-
this.
|
|
226
|
+
if (this.useLazyLoading) return
|
|
227
|
+
|
|
228
|
+
this.mx_filteredOptions = this.list
|
|
148
229
|
this.fuse = new Fuse(this.list, this.defaultFuseOptions)
|
|
149
|
-
|
|
230
|
+
|
|
231
|
+
this.setListWatcher()
|
|
150
232
|
},
|
|
151
233
|
|
|
152
234
|
methods: {
|
|
153
|
-
|
|
154
|
-
this.
|
|
155
|
-
? this.fuse.search(value)
|
|
156
|
-
: this.list
|
|
235
|
+
filterOptionsByFuse (value) {
|
|
236
|
+
this.mx_filteredOptions = value ? this.mx_getNormalizedFuseResults(this.fuse.search(value)) : this.list
|
|
157
237
|
},
|
|
158
238
|
|
|
159
|
-
|
|
160
|
-
|
|
239
|
+
async onInfiniteScroll (_, done) {
|
|
240
|
+
// Se tiver erro no primeiro fetch, retorna o "done" na proxima.
|
|
241
|
+
if (((this.mx_hasFetchError && !this.mx_hasFilteredOptions) || this.hasNoOptionsOnFirstFetch)) return done()
|
|
242
|
+
|
|
243
|
+
if (!this.mx_hasFilteredOptions && !this.mx_search) {
|
|
244
|
+
await this.mx_setFetchOptions()
|
|
245
|
+
return done()
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (this.mx_canFetchOptions()) {
|
|
249
|
+
await this.mx_loadMoreOptions()
|
|
250
|
+
return done()
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
done(true)
|
|
254
|
+
},
|
|
255
|
+
|
|
256
|
+
setListWatcher () {
|
|
257
|
+
this.$watch('list', value => {
|
|
258
|
+
this.fuse = new Fuse(value, this.defaultFuseOptions)
|
|
259
|
+
|
|
260
|
+
this.filterOptionsByFuse(this.mx_search)
|
|
261
|
+
}, { deep: true })
|
|
161
262
|
}
|
|
162
263
|
}
|
|
163
264
|
}
|
|
@@ -9,6 +9,24 @@ props:
|
|
|
9
9
|
default: 100px
|
|
10
10
|
type: String
|
|
11
11
|
|
|
12
|
+
empty-result-text:
|
|
13
|
+
desc: Define o texto dentro do box quando a lista está vazia.
|
|
14
|
+
default: Não há resultados disponíveis.
|
|
15
|
+
type: String
|
|
16
|
+
|
|
17
|
+
entity:
|
|
18
|
+
desc: Entidade enviada para a action "fetchFieldOptions" (usar somente quando "useLazyLoading" estiver habilitada).
|
|
19
|
+
default: ''
|
|
20
|
+
type: String
|
|
21
|
+
examples: [users]
|
|
22
|
+
|
|
23
|
+
fetching:
|
|
24
|
+
desc: Usado para saber quando o componente está fazendo fetching (usar somente quando "useLazyLoading" estiver habilitada).
|
|
25
|
+
default: false
|
|
26
|
+
type: Boolean
|
|
27
|
+
model: true
|
|
28
|
+
examples: [v-model:fetching="isFetching"]
|
|
29
|
+
|
|
12
30
|
fuse-options:
|
|
13
31
|
desc: Opções do Fuse.js (https://fusejs.io/api/options.html).
|
|
14
32
|
debugger: true
|
|
@@ -23,8 +41,18 @@ props:
|
|
|
23
41
|
default: 300px
|
|
24
42
|
type: String
|
|
25
43
|
|
|
44
|
+
lazy-loading-props:
|
|
45
|
+
desc: Propriedades para o lazy loading (usar somente quando "useLazyLoading" estiver habilitada).
|
|
46
|
+
type: Object
|
|
47
|
+
debugger: true
|
|
48
|
+
default:
|
|
49
|
+
decamelizeFieldName: true
|
|
50
|
+
url: ''
|
|
51
|
+
params:
|
|
52
|
+
limit: 48
|
|
53
|
+
|
|
26
54
|
list:
|
|
27
|
-
desc: Lista onde ocorrerá a busca
|
|
55
|
+
desc: Lista onde ocorrerá a busca sendo array de objetos (usar somente quando "useLazyLoading" **NÃO** estiver habilitada).
|
|
28
56
|
default: []
|
|
29
57
|
type: String
|
|
30
58
|
|
|
@@ -34,6 +62,11 @@ props:
|
|
|
34
62
|
examples: [v-model="search"]
|
|
35
63
|
model: true
|
|
36
64
|
|
|
65
|
+
name:
|
|
66
|
+
desc: Nome do campo a ser enviado para a action "fetchFieldOptions" (usar somente quando "useLazyLoading" estiver habilitada).
|
|
67
|
+
type: String
|
|
68
|
+
examples: [cities]
|
|
69
|
+
|
|
37
70
|
placeholder:
|
|
38
71
|
desc: Placeholder do campo de pesquisa.
|
|
39
72
|
default: Pesquisar
|
|
@@ -51,6 +84,11 @@ props:
|
|
|
51
84
|
default: true
|
|
52
85
|
type: Boolean
|
|
53
86
|
|
|
87
|
+
use-lazy-loading:
|
|
88
|
+
desc: Controla a busca pela store "fetchFieldOptions".
|
|
89
|
+
default: false
|
|
90
|
+
type: Boolean
|
|
91
|
+
|
|
54
92
|
slots:
|
|
55
93
|
default:
|
|
56
94
|
desc: Acesso ao conteúdo principal, só existe caso a busca retorne algum resultado.
|
|
@@ -58,6 +96,9 @@ slots:
|
|
|
58
96
|
empty-result:
|
|
59
97
|
desc: Acesso ao conteúdo quando a busca não retorne resultado e a prop "useEmptySlot" seja "true".
|
|
60
98
|
|
|
99
|
+
loading:
|
|
100
|
+
desc: Acesso ao conteúdo do loading que contém o "<q-spinner-dots />"..
|
|
101
|
+
|
|
61
102
|
events:
|
|
62
103
|
'@empty-result -> function ()':
|
|
63
104
|
desc: Dispara toda vez que a pesquisa não retorna resultado.
|
|
@@ -76,3 +117,27 @@ events:
|
|
|
76
117
|
desc: Novo valor do v-model:results
|
|
77
118
|
default: []
|
|
78
119
|
type: Array
|
|
120
|
+
|
|
121
|
+
'@update:fetching -> function (value)':
|
|
122
|
+
desc: Dispara toda vez que o campo de busca faz o fetch do lazy loading
|
|
123
|
+
params:
|
|
124
|
+
value:
|
|
125
|
+
desc: Novo valor do v-model:fetching
|
|
126
|
+
default: false
|
|
127
|
+
type: Boolean
|
|
128
|
+
|
|
129
|
+
'@fetch-options-success -> function (value)':
|
|
130
|
+
desc: Dispara toda vez que o campo de busca faz o fetch do lazy loading com sucesso.
|
|
131
|
+
params:
|
|
132
|
+
value:
|
|
133
|
+
desc: Valor retornado pela action "fetchFieldOptions"
|
|
134
|
+
default: {}
|
|
135
|
+
type: Object
|
|
136
|
+
|
|
137
|
+
'@fetch-options-error -> function (value)':
|
|
138
|
+
desc: Dispara toda vez que o campo de busca faz o fetch do lazy loading e cai em uma exceção.
|
|
139
|
+
params:
|
|
140
|
+
value:
|
|
141
|
+
desc: Valor retornado pela action "fetchFieldOptions"
|
|
142
|
+
default: {}
|
|
143
|
+
type: Object
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<q-select v-model="model" v-bind="attributes"
|
|
2
|
+
<q-select v-model="model" v-bind="attributes">
|
|
3
3
|
<template #append>
|
|
4
4
|
<slot name="append">
|
|
5
|
-
<q-icon v-if="
|
|
5
|
+
<q-icon v-if="isSearchable" name="o_search" />
|
|
6
6
|
</slot>
|
|
7
7
|
</template>
|
|
8
8
|
|
|
9
9
|
<template #no-option>
|
|
10
|
-
<slot name="no-option">
|
|
10
|
+
<slot v-if="!mx_isFetching" name="no-option">
|
|
11
11
|
<q-item>
|
|
12
12
|
<q-item-section class="text-grey">
|
|
13
13
|
{{ noOptionLabel }}
|
|
@@ -16,6 +16,14 @@
|
|
|
16
16
|
</slot>
|
|
17
17
|
</template>
|
|
18
18
|
|
|
19
|
+
<template #after-options>
|
|
20
|
+
<slot v-if="mx_isFetching" name="after-options">
|
|
21
|
+
<div class="flex justify-center q-pb-sm">
|
|
22
|
+
<q-spinner-dots color="primary" size="20px" />
|
|
23
|
+
</div>
|
|
24
|
+
</slot>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
19
27
|
<template v-for="(_, name) in $slots" #[name]="context">
|
|
20
28
|
<slot :name="name" v-bind="context || {}" />
|
|
21
29
|
</template>
|
|
@@ -23,11 +31,14 @@
|
|
|
23
31
|
</template>
|
|
24
32
|
|
|
25
33
|
<script>
|
|
34
|
+
import { searchFilterMixin } from '../../mixins'
|
|
26
35
|
import Fuse from 'fuse.js'
|
|
27
36
|
|
|
28
37
|
export default {
|
|
29
38
|
name: 'QasSelect',
|
|
30
39
|
|
|
40
|
+
mixins: [searchFilterMixin],
|
|
41
|
+
|
|
31
42
|
props: {
|
|
32
43
|
fuseOptions: {
|
|
33
44
|
default: () => ({}),
|
|
@@ -41,7 +52,7 @@ export default {
|
|
|
41
52
|
|
|
42
53
|
modelValue: {
|
|
43
54
|
default: () => [],
|
|
44
|
-
type: [Array, Object, String, Number]
|
|
55
|
+
type: [Array, Object, String, Number, Boolean]
|
|
45
56
|
},
|
|
46
57
|
|
|
47
58
|
noOptionLabel: {
|
|
@@ -54,13 +65,13 @@ export default {
|
|
|
54
65
|
type: Array
|
|
55
66
|
},
|
|
56
67
|
|
|
57
|
-
searchable: {
|
|
58
|
-
type: Boolean
|
|
59
|
-
},
|
|
60
|
-
|
|
61
68
|
valueKey: {
|
|
62
69
|
default: '',
|
|
63
70
|
type: String
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
useSearch: {
|
|
74
|
+
type: Boolean
|
|
64
75
|
}
|
|
65
76
|
},
|
|
66
77
|
|
|
@@ -68,7 +79,6 @@ export default {
|
|
|
68
79
|
|
|
69
80
|
data () {
|
|
70
81
|
return {
|
|
71
|
-
filteredOptions: [],
|
|
72
82
|
fuse: null
|
|
73
83
|
}
|
|
74
84
|
},
|
|
@@ -76,15 +86,18 @@ export default {
|
|
|
76
86
|
computed: {
|
|
77
87
|
attributes () {
|
|
78
88
|
return {
|
|
79
|
-
clearable: this.
|
|
89
|
+
clearable: this.isSearchable,
|
|
80
90
|
emitValue: true,
|
|
81
91
|
mapOptions: true,
|
|
82
92
|
outlined: true,
|
|
83
|
-
|
|
84
93
|
...this.$attrs,
|
|
85
94
|
|
|
86
|
-
options: this.
|
|
87
|
-
useInput: this.
|
|
95
|
+
options: this.mx_filteredOptions,
|
|
96
|
+
useInput: this.isSearchable,
|
|
97
|
+
error: this.hasError,
|
|
98
|
+
loading: this.hasLoading,
|
|
99
|
+
...(this.useLazyLoading && { onVirtualScroll: this.mx_onVirtualScroll }),
|
|
100
|
+
...(this.isSearchable && { onFilter: this.onFilter })
|
|
88
101
|
}
|
|
89
102
|
},
|
|
90
103
|
|
|
@@ -98,12 +111,20 @@ export default {
|
|
|
98
111
|
}
|
|
99
112
|
},
|
|
100
113
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
114
|
+
isSearchable () {
|
|
115
|
+
return this.useSearch || this.useLazyLoading
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
defaultOptions () {
|
|
119
|
+
return this.mx_handleOptions(this.options)
|
|
120
|
+
},
|
|
105
121
|
|
|
106
|
-
|
|
122
|
+
hasError () {
|
|
123
|
+
return this.mx_hasFetchError || this.$attrs.error
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
hasLoading () {
|
|
127
|
+
return this.mx_isFetching || this.$attrs.loading
|
|
107
128
|
},
|
|
108
129
|
|
|
109
130
|
model: {
|
|
@@ -124,11 +145,11 @@ export default {
|
|
|
124
145
|
|
|
125
146
|
options: {
|
|
126
147
|
handler () {
|
|
127
|
-
if (this.
|
|
128
|
-
|
|
129
|
-
|
|
148
|
+
if (this.useLazyLoading && this.mx_hasFilteredOptions) return
|
|
149
|
+
|
|
150
|
+
if (this.fuse) this.setFuse()
|
|
130
151
|
|
|
131
|
-
this.
|
|
152
|
+
this.mx_filteredOptions = this.defaultOptions
|
|
132
153
|
},
|
|
133
154
|
|
|
134
155
|
immediate: true
|
|
@@ -137,42 +158,37 @@ export default {
|
|
|
137
158
|
|
|
138
159
|
created () {
|
|
139
160
|
this.setFuse()
|
|
161
|
+
this.useLazyLoading && this.mx_setFetchOptions('')
|
|
140
162
|
},
|
|
141
163
|
|
|
142
164
|
methods: {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
if (value === '') {
|
|
148
|
-
this.filteredOptions = this.formattedResult
|
|
149
|
-
} else {
|
|
150
|
-
const results = this.fuse.search(value)
|
|
151
|
-
this.filteredOptions = results.map(item => item.item)
|
|
152
|
-
}
|
|
153
|
-
})
|
|
165
|
+
setFuse () {
|
|
166
|
+
if (this.useSearch) {
|
|
167
|
+
this.fuse = new Fuse(this.defaultOptions, this.defaultFuseOptions)
|
|
168
|
+
}
|
|
154
169
|
},
|
|
155
170
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
value: this.valueKey
|
|
171
|
+
async onFilter (value, update) {
|
|
172
|
+
if (this.useLazyLoading && value !== this.mx_search) {
|
|
173
|
+
await this.mx_filterOptionsByStore(value)
|
|
160
174
|
}
|
|
161
175
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
item[newKey] = item[mapKeys[newKey]]
|
|
165
|
-
delete item[mapKeys[newKey]]
|
|
166
|
-
}
|
|
176
|
+
if (!this.useLazyLoading && this.useSearch) {
|
|
177
|
+
this.filterOptionsByFuse(value)
|
|
167
178
|
}
|
|
168
179
|
|
|
169
|
-
|
|
180
|
+
update()
|
|
170
181
|
},
|
|
171
182
|
|
|
172
|
-
|
|
173
|
-
if (
|
|
174
|
-
this.
|
|
183
|
+
filterOptionsByFuse (value) {
|
|
184
|
+
if (value === '') {
|
|
185
|
+
this.mx_filteredOptions = this.defaultOptions
|
|
186
|
+
return
|
|
175
187
|
}
|
|
188
|
+
|
|
189
|
+
const results = this.fuse.search(value)
|
|
190
|
+
|
|
191
|
+
this.mx_filteredOptions = this.mx_getNormalizedFuseResults(results)
|
|
176
192
|
}
|
|
177
193
|
}
|
|
178
194
|
}
|
|
@@ -7,6 +7,19 @@ meta:
|
|
|
7
7
|
desc: Componente para select que implementa o "QSelect" repassando propriedades, slots e eventos.
|
|
8
8
|
|
|
9
9
|
props:
|
|
10
|
+
entity:
|
|
11
|
+
desc: Entidade enviada para a action "fetchFieldOptions" (usar somente quando "useLazyLoading" estiver habilitada).
|
|
12
|
+
default: ''
|
|
13
|
+
type: String
|
|
14
|
+
examples: [users]
|
|
15
|
+
|
|
16
|
+
fetching:
|
|
17
|
+
desc: Usado para saber quando o componente está fazendo fetching (usar somente quando "useLazyLoading" estiver habilitada).
|
|
18
|
+
default: false
|
|
19
|
+
type: Boolean
|
|
20
|
+
model: true
|
|
21
|
+
examples: [v-model:fetching="isFetching"]
|
|
22
|
+
|
|
10
23
|
fuse-options:
|
|
11
24
|
desc: Opções do Fuse.js (https://fusejs.io/api/options.html).
|
|
12
25
|
type: Object
|
|
@@ -21,13 +34,28 @@ props:
|
|
|
21
34
|
type: String
|
|
22
35
|
examples: [label-key="name"]
|
|
23
36
|
|
|
37
|
+
lazy-loading-props:
|
|
38
|
+
desc: Propriedades para o lazy loading (usar somente quando "useLazyLoading" estiver habilitada).
|
|
39
|
+
type: Object
|
|
40
|
+
debugger: true
|
|
41
|
+
default:
|
|
42
|
+
decamelizeFieldName: true
|
|
43
|
+
url: ''
|
|
44
|
+
params:
|
|
45
|
+
limit: 48
|
|
46
|
+
|
|
24
47
|
model-value:
|
|
25
48
|
desc: Model do componente.
|
|
26
49
|
default: []
|
|
27
|
-
type: [Array, Object, String, Number]
|
|
50
|
+
type: [Array, Object, String, Number, Boolean]
|
|
28
51
|
examples: [v-model="value"]
|
|
29
52
|
model: true
|
|
30
53
|
|
|
54
|
+
name:
|
|
55
|
+
desc: Nome do campo a ser enviado para a action "fetchFieldOptions" (usar somente quando "useLazyLoading" estiver habilitada).
|
|
56
|
+
type: String
|
|
57
|
+
examples: [cities]
|
|
58
|
+
|
|
31
59
|
no-option-label:
|
|
32
60
|
desc: Rótulo padrão de quando os options estão vazios.
|
|
33
61
|
default: Nenhum resultado foi encontrado.
|
|
@@ -38,19 +66,48 @@ props:
|
|
|
38
66
|
default: []
|
|
39
67
|
type: Array
|
|
40
68
|
|
|
41
|
-
searchable:
|
|
42
|
-
desc: Controla se vai ou não ter campo de busca no select.
|
|
43
|
-
type: Boolean
|
|
44
|
-
|
|
45
69
|
value-key:
|
|
46
70
|
desc: O componente internamente espera receber na propriedade "options" um array de objeto contendo "label" e "value", caso o seu objeto não tenha "value" mas um "uuid" por exemplo, você pode definir esta prop "label-value" como "uuid".
|
|
47
71
|
type: String
|
|
48
72
|
examples: [value-key="uuid"]
|
|
49
73
|
|
|
74
|
+
use-search:
|
|
75
|
+
desc: Controla se vai ou não ter campo de busca no select.
|
|
76
|
+
type: Boolean
|
|
77
|
+
|
|
78
|
+
use-lazy-loading:
|
|
79
|
+
desc: Controla a busca pela store "fetchFieldOptions".
|
|
80
|
+
default: false
|
|
81
|
+
type: Boolean
|
|
82
|
+
|
|
50
83
|
events:
|
|
51
84
|
'@update:model-value -> function (value)':
|
|
52
85
|
desc: Dispara toda vez que o model é atualizado, também utilizado para v-model.
|
|
53
86
|
params:
|
|
54
87
|
value:
|
|
55
88
|
desc: Novo valor do v-model
|
|
56
|
-
type: [Array, Object, String, Number]
|
|
89
|
+
type: [Array, Object, String, Number, Boolean]
|
|
90
|
+
|
|
91
|
+
'@update:fetching -> function (value)':
|
|
92
|
+
desc: Dispara toda vez que o campo de busca faz o fetch do lazy loading
|
|
93
|
+
params:
|
|
94
|
+
value:
|
|
95
|
+
desc: Novo valor do v-model:fetching
|
|
96
|
+
default: false
|
|
97
|
+
type: Boolean
|
|
98
|
+
|
|
99
|
+
'@fetch-options-success -> function (value)':
|
|
100
|
+
desc: Dispara toda vez que o campo de busca faz o fetch do lazy loading com sucesso.
|
|
101
|
+
params:
|
|
102
|
+
value:
|
|
103
|
+
desc: Valor retornado pela action "fetchFieldOptions"
|
|
104
|
+
default: {}
|
|
105
|
+
type: Object
|
|
106
|
+
|
|
107
|
+
'@fetch-options-error -> function (value)':
|
|
108
|
+
desc: Dispara toda vez que o campo de busca faz o fetch do lazy loading e cai em uma exceção.
|
|
109
|
+
params:
|
|
110
|
+
value:
|
|
111
|
+
desc: Valor retornado pela action "fetchFieldOptions"
|
|
112
|
+
default: {}
|
|
113
|
+
type: Object
|