# Cascader
级联选择器
# Markup Schema 案例
<template>
<Form :form="form">
<SchemaField>
<SchemaStringField
name="address"
title="地址选择"
required
x-decorator="FormItem"
x-component="Cascader"
:x-component-props="{
style: {
width: '240px',
},
}"
/>
</SchemaField>
<Submit @submit="onSubmit">提交</Submit>
</Form>
</template>
<script>
import { createForm, onFieldReact } from '@formily/core'
import { createSchemaField } from '@formily/vue'
import { Form, FormItem, Cascader, Submit } from '@formily/antdv'
import { action } from '@formily/reactive'
import axios from 'axios'
const transformAddress = (data = {}) => {
return Object.entries(data).reduce((buf, [key, value]) => {
if (typeof value === 'string')
return buf.concat({
label: value,
value: key,
})
const { name, code, cities, districts } = value
const _cities = transformAddress(cities)
const _districts = transformAddress(districts)
return buf.concat({
label: name,
value: code,
children: _cities.length
? _cities
: _districts.length
? _districts
: undefined,
})
}, [])
}
const useAddress = (pattern) => {
onFieldReact(pattern, (field) => {
field.loading = true
axios('https://unpkg.com/china-location/dist/location.json')
.then((res) => res.data)
.then(
action.bound((data) => {
field.dataSource = transformAddress(data)
field.loading = false
})
)
})
}
const form = createForm({
effects: () => {
useAddress('address')
},
})
const fields = createSchemaField({
components: {
FormItem,
Cascader,
},
})
export default {
components: { Form, ...fields, Submit },
data() {
return {
form,
}
},
methods: {
onSubmit(value) {
console.log(value)
},
},
}
</script>
l
# JSON Schema 案例
<template>
<Form :form="form">
<SchemaField
:schema="schema"
:scope="{ useAsyncDataSource, transformAddress }"
/>
<Submit @submit="onSubmit">提交</Submit>
</Form>
</template>
<script>
import { createForm } from '@formily/core'
import { createSchemaField } from '@formily/vue'
import { Form, FormItem, Cascader, Submit } from '@formily/antdv'
import { action } from '@formily/reactive'
import axios from 'axios'
const transformAddress = (data = {}) => {
return Object.entries(data).reduce((buf, [key, value]) => {
if (typeof value === 'string')
return buf.concat({
label: value,
value: key,
})
const { name, code, cities, districts } = value
const _cities = transformAddress(cities)
const _districts = transformAddress(districts)
return buf.concat({
label: name,
value: code,
children: _cities.length
? _cities
: _districts.length
? _districts
: undefined,
})
}, [])
}
const useAsyncDataSource = (url, transform) => {
return (field) => {
field.loading = true
axios
.get(url)
.then((res) => res.data)
.then(
action.bound((data) => {
field.dataSource = transform(data)
field.loading = false
})
)
}
}
const schema = {
type: 'object',
properties: {
cascader: {
type: 'string',
title: '地址选择',
'x-decorator': 'FormItem',
'x-component': 'Cascader',
'x-component-props': {
style: {
width: '240px',
},
},
'x-reactions': [
'{{useAsyncDataSource("https://unpkg.com/china-location/dist/location.json",transformAddress)}}',
],
},
},
}
const form = createForm()
const { SchemaField } = createSchemaField({
components: {
FormItem,
Cascader,
},
})
export default {
components: { Form, SchemaField, Submit },
data() {
return {
useAsyncDataSource,
transformAddress,
form,
schema,
}
},
methods: {
onSubmit(value) {
console.log(value)
},
},
}
</script>
l
# Template 案例
<template>
<Form :form="form">
<Field
name="address"
title="地址选择"
required
:decorator="[FormItem]"
:component="[
Cascader,
{
style: {
width: '240px',
},
},
]"
/>
<Submit @submit="onSubmit">提交</Submit>
</Form>
</template>
<script>
import { createForm, onFieldReact } from '@formily/core'
import { Field } from '@formily/vue'
import { Form, FormItem, Cascader, Submit } from '@formily/antdv'
import { action } from '@formily/reactive'
import axios from 'axios'
const transformAddress = (data = {}) => {
return Object.entries(data).reduce((buf, [key, value]) => {
if (typeof value === 'string')
return buf.concat({
label: value,
value: key,
})
const { name, code, cities, districts } = value
const _cities = transformAddress(cities)
const _districts = transformAddress(districts)
return buf.concat({
label: name,
value: code,
children: _cities.length
? _cities
: _districts.length
? _districts
: undefined,
})
}, [])
}
const useAddress = (pattern) => {
onFieldReact(pattern, (field) => {
field.loading = true
axios('https://unpkg.com/china-location/dist/location.json')
.then((res) => res.data)
.then(
action.bound((data) => {
field.dataSource = transformAddress(data)
field.loading = false
})
)
})
}
const form = createForm({
effects: () => {
useAddress('address')
},
})
export default {
components: { Form, Field, Submit },
data() {
return {
FormItem,
Cascader,
form,
}
},
methods: {
onSubmit(value) {
console.log(value)
},
},
}
</script>
# API
参考 https://antdv.com/components/cascader-cn/ (opens new window)