Skip to content

Commit

Permalink
feat(grid-select): add remote feature (#2530)
Browse files Browse the repository at this point in the history
  • Loading branch information
kagol authored Nov 19, 2024
1 parent 469742f commit d77c5ee
Show file tree
Hide file tree
Showing 10 changed files with 250 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
<p>场景2:多选</p>
<br />
<tiny-grid-select
v-model="valueMulti"
v-model="valueMultiple"
multiple
value-field="id"
text-field="city"
:grid-op="gridOpMulti"
:grid-op="gridOpMultiple"
:select-config="selectConfig"
></tiny-grid-select>
</div>
Expand All @@ -28,7 +28,7 @@ import { ref, reactive } from 'vue'
import { TinyGridSelect } from '@opentiny/vue'
const valueSingle = ref('')
const valueMulti = ref([])
const valueMultiple = ref([])
const gridOpSingle = reactive({
data: [
Expand All @@ -46,7 +46,7 @@ const gridOpSingle = reactive({
]
})
const gridOpMulti = reactive({
const gridOpMultiple = reactive({
data: [
{ id: '001', area: '华南区', province: '广东省', city: '广州市' },
{ id: '002', area: '华南区', province: '广东省', city: '深圳市' },
Expand Down
13 changes: 12 additions & 1 deletion examples/sites/demos/pc/app/grid-select/filter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default {
},
data() {
return {
valueSingle: [],
valueSingle: '',
gridOpSingle: {
data: [
{ id: '001', area: '华南区', province: '广东省', city: '广州市' },
Expand All @@ -35,6 +35,17 @@ export default {
]
}
}
},
methods: {
filter(value) {
if (!value) {
return this.gridOpSingle.data
}
return this.gridOpSingle.data.filter((item) => {
return item.city.includes(value)
})
}
}
}
</script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<tiny-grid-select
v-model="value"
multiple
:grid-op="gridOpMulti"
:grid-op="gridOpMultiple"
value-field="id"
text-field="city"
></tiny-grid-select>
Expand All @@ -14,7 +14,7 @@ import { GridSelect as TinyGridSelect } from '@opentiny/vue'
const value = ref('')
const gridOpMulti = reactive({
const gridOpMultiple = reactive({
data: [
{ id: '001', area: '华南区', province: '广东省', city: '广州市' },
{ id: '002', area: '华南区', province: '广东省', city: '深圳市' },
Expand Down
4 changes: 2 additions & 2 deletions examples/sites/demos/pc/app/grid-select/multiple.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<tiny-grid-select
v-model="value"
multiple
:grid-op="gridOpMulti"
:grid-op="gridOpMultiple"
value-field="id"
text-field="city"
></tiny-grid-select>
Expand All @@ -18,7 +18,7 @@ export default {
data() {
return {
value: [],
treeOp: {
gridOpMultiple: {
data: [
{ id: '001', area: '华南区', province: '广东省', city: '广州市' },
{ id: '002', area: '华南区', province: '广东省', city: '深圳市' },
Expand Down
84 changes: 84 additions & 0 deletions examples/sites/demos/pc/app/grid-select/remote-composition-api.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<template>
<div>
<p>场景1:单选</p>
<br />
<tiny-grid-select
v-model="valueSingle"
:grid-op="gridOpSingle"
filterable
remote
:remote-method="remoteMethod"
></tiny-grid-select>
<br /><br />
<p>场景2:多选</p>
<br />
<tiny-grid-select
v-model="valueMultiple"
:grid-op="gridOpMultiple"
multiple
filterable
remote
:remote-method="remoteMethod"
></tiny-grid-select>
</div>
</template>

<script setup>
import { ref, reactive } from 'vue'
import { TinyGridSelect } from '@opentiny/vue'
const valueSingle = ref('')
const valueMultiple = ref([])
const gridOpSingle = reactive({
data: [],
height: 300,
columns: [
{ type: 'radio', title: '' },
{ field: 'area', title: '区域', width: 90 },
{ field: 'province', title: '省份', width: 60 },
{ field: 'city', title: '城市', width: 60 }
]
})
const gridOpMultiple = reactive({
data: [],
height: 300,
columns: [
{ type: 'selection', title: '' },
{ field: 'area', title: '区域', width: 90 },
{ field: 'province', title: '省份', width: 60 },
{ field: 'city', title: '城市', width: 60 }
]
})
const allData = Array.from({ length: 1000 }, (a, i) => {
return {
value: '00' + i,
province: '省份' + i,
city: '城市' + i,
area: '区域' + i,
label: `${i}-市${i}`
}
})
const filter = (value) => {
return allData.filter((item) => item.city.includes(value))
}
const remoteMethod = (value) => {
const filterData = filter(value)
return new Promise((resolve) => {
setTimeout(() => {
resolve(filterData)
}, 500)
})
}
</script>

<style scoped>
.tiny-grid-select {
width: 280px;
}
</style>
89 changes: 89 additions & 0 deletions examples/sites/demos/pc/app/grid-select/remote.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<template>
<div>
<p>场景1:单选</p>
<br />
<tiny-grid-select
v-model="valueSingle"
:grid-op="gridOpSingle"
filterable
remote
:remote-method="remoteMethod"
></tiny-grid-select>
<br /><br />
<p>场景2:多选</p>
<br />
<tiny-grid-select
v-model="valueMultiple"
:grid-op="gridOpMultiple"
multiple
filterable
remote
:remote-method="remoteMethod"
></tiny-grid-select>
</div>
</template>

<script>
import { TinyGridSelect } from '@opentiny/vue'
export default {
components: {
TinyGridSelect
},
data() {
return {
valueSingle: '',
valueMultiple: [],
gridOpSingle: {
data: [],
height: 300,
columns: [
{ type: 'radio', title: '' },
{ field: 'area', title: '区域', width: 90 },
{ field: 'province', title: '省份', width: 60 },
{ field: 'city', title: '城市', width: 60 }
]
},
gridOpMultiple: {
data: [],
height: 300,
columns: [
{ type: 'selection', title: '' },
{ field: 'area', title: '区域', width: 90 },
{ field: 'province', title: '省份', width: 60 },
{ field: 'city', title: '城市', width: 60 }
]
},
allData: Array.from({ length: 1000 }, (a, i) => {
return {
value: '00' + i,
province: '省份' + i,
city: '城市' + i,
area: '区域' + i,
label: `${i}-市${i}`
}
})
}
},
methods: {
filter(value) {
return this.allData.filter((item) => item.city.includes(value))
},
remoteMethod(value) {
const filterData = this.filter(value)
return new Promise((resolve) => {
setTimeout(() => {
resolve(filterData)
}, 500)
})
}
}
}
</script>

<style scoped>
.tiny-grid-select {
width: 280px;
}
</style>
18 changes: 15 additions & 3 deletions examples/sites/demos/pc/app/grid-select/webdoc/grid-select.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,24 @@ export default {
'en-US': 'Filterable'
},
desc: {
'zh-CN':
'<p>通过 <code>filterable</code> 设置是否可过滤,<code>filter-method</code> 设置自定义过滤逻辑。</p>\n',
'zh-CN': '<p>通过 <code>filterable</code> 设置是否可过滤,<code>filter-method</code> 设置自定义过滤逻辑。</p>',
'en-US': ''
},
codeFiles: ['filter.vue']
},
{
demoId: 'remote',
name: {
'zh-CN': '远程搜索',
'en-US': 'Remote search'
},
desc: {
'zh-CN':
'<p>同时使用 <code>remote</code> 和 <code>remote-method</code> 和 <code>filterable</code> 3个属性开启远程搜索。通过 <code>remote-config</code> 设置自动搜索和显示展开按钮。<br>在多选模式下,可通过 <code>reserve-keyword</code> 设置选中一个选项后依然保留搜索关键字。</p>',
'en-US': ''
},
codeFiles: ['remote.vue']
},
{
demoId: 'config',
name: {
Expand All @@ -52,7 +64,7 @@ export default {
},
desc: {
'zh-CN':
'<p>通过 <code>select-config</code> (多选)或 <code>radio-config</code> (单选)属性的 <code>checkMethod</code> 自定义禁用逻辑,返回 true (启用) / false (禁用)。配置 <code>{ trigger: "row" }</code> 可以设置点击行选中数据。</p>\n',
'<p>通过 <code>select-config</code> (多选)或 <code>radio-config</code> (单选)属性的 <code>checkMethod</code> 自定义禁用逻辑,返回 true (启用) / false (禁用)。<br>配置 <code>{ trigger: "row" }</code> 可以设置点击行选中数据。</p>',
'en-US':
"<p>By customizing the disable logic through the <code>select-config</code> (multiple selection) or <code>radio-config</code> (single selection) attribute's <code>checkMethod</code>, return true (Enable) / false (disable).Configure {trigger: 'row'} to set the selected data in the click row.</p>"
},
Expand Down
16 changes: 8 additions & 8 deletions examples/sites/demos/pc/menus.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,14 @@ export const cmpMenus = [
{ 'nameCn': '文件上传', 'name': 'FileUpload', 'key': 'file-upload' },
{ 'nameCn': '富文本', 'name': 'FluentEditor', 'key': 'fluent-editor' },
{ 'nameCn': '表单', 'name': 'Form', 'key': 'form' },
{
'nameCn': '下拉表格选择器',
'name': 'GridSelect',
'key': 'grid-select',
'meta': {
'experimental': '3.20.0'
}
},
// {
// 'nameCn': '下拉表格选择器',
// 'name': 'GridSelect',
// 'key': 'grid-select',
// 'meta': {
// 'experimental': '3.20.0'
// }
// },
{ 'nameCn': '输入框', 'name': 'Input', 'key': 'input' },
{ 'nameCn': ' IP地址输入框', 'name': 'IpAddress', 'key': 'ip-address' },
{ 'nameCn': '数字输入框', 'name': 'Numeric', 'key': 'numeric' },
Expand Down
38 changes: 31 additions & 7 deletions packages/renderless/src/grid-select/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,42 @@ export const buildRadioConfig =
export const filter =
({ props, state, vm }) =>
(value) => {
const { filterMethod } = props
const { multiple, valueField, filterMethod, remote, remoteMethod } = props

const table = vm.$refs.gridRef.$refs.tinyTable
const fullData = table.afterFullData
if ((props.filterable || props.searchable) && typeof filterMethod === 'function') {
const table = vm.$refs.gridRef.$refs.tinyTable
const fullData = table.afterFullData

vm.$refs.gridRef.scrollTo(null, 0)
vm.$refs.gridRef.scrollTo(null, 0)

table.afterFullData = filterMethod(value, fullData) || []
table.afterFullData = filterMethod(value, fullData) || []

vm.$refs.gridRef.handleTableData(!value)
vm.$refs.gridRef.handleTableData(!value)

state.previousQuery = value
state.previousQuery = value
} else if (remote && typeof remoteMethod === 'function') {
state.previousQuery = value
remoteMethod(value, props.extraQueryParams).then((data) => {
// 多选时取远端数据与当前已选数据的并集
if (multiple) {
const selectedIds = state.selected.map((sel) => sel[valueField])
vm.$refs.gridRef.clearSelection()
vm.$refs.gridRef.setSelection(
data.filter((row) => ~selectedIds.indexOf(row[valueField])),
true
)
state.remoteData = data.filter((row) => !~selectedIds.indexOf(row[valueField])).concat(state.selected)
} else {
vm.$refs.gridRef.clearRadioRow()
vm.$refs.gridRef.setRadioRow(find(data, (item) => props.modelValue === item[props.valueField]))
state.remoteData = data
}

vm.$refs.gridRef.$refs.tinyTable.lastScrollTop = 0
vm.$refs.gridRef.loadData(data)
vm.$refs.gridRef.handleTableData(!value)
})
}
}

export const radioChange =
Expand Down
4 changes: 3 additions & 1 deletion packages/renderless/src/grid-select/vue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ export const renderless = (props, { reactive, watch }, { vm, emit }) => {

const state = reactive({
value: props.modelValue,
gridData: props.gridOp.data
gridData: props.gridOp.data,
remoteData: [],
selected: props.multiple ? [] : {}
})

Object.assign(api, {
Expand Down

0 comments on commit d77c5ee

Please sign in to comment.