Cascader カスケードセレクト
カスケードセレクトは複数階層のデータを扱う場面で使用します。例:省・市・地区の選択。
基本的な使い方
単独で使用
vue
<script setup>
import { ref } from 'vue'
const value1 = ref([])
const options1 = [
{
value: 'zhinan',
label: 'ガイド',
children: [
{
value: 'sheji',
label: 'デザインガイド',
children: [
{ value: 'yuansze', label: '色' },
{ value: 'fuziyuanze', label: 'フォント' },
],
},
{
value: 'shejiguize',
label: 'デザインルール',
},
],
},
{
value: 'zujian',
label: 'コンポーネント',
children: [
{ value: 'jiben', label: '基本' },
{ value: 'fankui', label: 'フィードバック' },
],
},
]
</script>
<template>
<!-- 基本的な使い方 -->
<lh-cascader v-model="value1" :options="options1" />
</template>vue
<script>
export default {
data() {
return {
value1: [],
options1: [
{
value: 'zhinan',
label: 'ガイド',
children: [
{
value: 'sheji',
label: 'デザインガイド',
children: [
{ value: 'yuansze', label: '色' },
{ value: 'fuziyuanze', label: 'フォント' },
],
},
{
value: 'shejiguize',
label: 'デザインルール',
},
],
},
{
value: 'zujian',
label: 'コンポーネント',
children: [
{ value: 'jiben', label: '基本' },
{ value: 'fankui', label: 'フィードバック' },
],
},
],
}
},
}
</script>
<template>
<!-- 基本的な使い方 -->
<lh-cascader v-model="value1" :options="options1" />
</template>複数選択モード
複数選択モードを設定すると、複数の結果を選択できます。
複数選択モード
vue
<script setup>
import { ref } from 'vue'
const value2 = ref([])
const options2 = [
{
value: 'zhinan',
label: 'ガイド',
children: [
{ value: 'sheji', label: 'デザインガイド' },
{ value: 'shejiguize', label: 'デザインルール' },
],
},
{
value: 'zujian',
label: 'コンポーネント',
children: [
{ value: 'jiben', label: '基本コンポーネント' },
{ value: 'fankui', label: 'フィードバックコンポーネント' },
],
},
]
</script>
<template>
<!-- 複数選択モード -->
<lh-cascader v-model="value2" :options="options2" multiple />
</template>vue
<script>
export default {
data() {
return {
value2: [],
options2: [
{
value: 'zhinan',
label: 'ガイド',
children: [
{ value: 'sheji', label: 'デザインガイド' },
{ value: 'shejiguize', label: 'デザインルール' },
],
},
{
value: 'zujian',
label: 'コンポーネント',
children: [
{ value: 'jiben', label: '基本コンポーネント' },
{ value: 'fankui', label: 'フィードバックコンポーネント' },
],
},
],
}
},
}
</script>
<template>
<!-- 複数選択モード -->
<lh-cascader v-model="value2" :options="options2" multiple />
</template>オプションの無効化
disabled 属性でノードを無効化します。
オプションの無効化
vue
<script setup>
import { ref } from 'vue'
const value3 = ref([])
const options3 = [
{
value: 'zhinan',
label: 'ガイド',
disabled: true,
children: [
{ value: 'sheji', label: 'デザインガイド' },
],
},
{
value: 'zujian',
label: 'コンポーネント',
children: [
{ value: 'jiben', label: '基本コンポーネント' },
{ value: 'fankui', label: 'フィードバックコンポーネント', disabled: true },
],
},
]
</script>
<template>
<!-- オプションの無効化 -->
<lh-cascader v-model="value3" :options="options3" />
</template>vue
<script>
export default {
data() {
return {
value3: [],
options3: [
{
value: 'zhinan',
label: 'ガイド',
disabled: true,
children: [
{ value: 'sheji', label: 'デザインガイド' },
],
},
{
value: 'zujian',
label: 'コンポーネント',
children: [
{ value: 'jiben', label: '基本コンポーネント' },
{ value: 'fankui', label: 'フィードバックコンポーネント', disabled: true },
],
},
],
}
},
}
</script>
<template>
<!-- オプションの無効化 -->
<lh-cascader v-model="value3" :options="options3" />
</template>サイズ・無効化・読み取り専用
size でサイズを調整し、disabled でセレクタ全体を無効化し、readonly で読み取り専用表示にし、placeholder でプレースホルダーをカスタマイズし、clearable でクリアボタンをオフにします。
サイズ・無効化・読み取り専用
vue
<script setup lang="ts">
import { ref } from 'vue'
const demoCascSize = ref([])
const demoCascSize2 = ref([])
const demoCascDisabled = ref([])
const demoCascReadonly = ref([])
const demoCascPlaceholder = ref([])
const demoCascNoClear = ref([])
const options = [
{
value: 'zhinan',
label: 'ガイド',
children: [
{ value: 'sheji', label: 'デザインガイド' },
{ value: 'shejiguize', label: 'デザインルール' },
],
},
{
value: 'zujian',
label: 'コンポーネント',
children: [
{ value: 'jiben', label: '基本コンポーネント' },
{ value: 'fankui', label: 'フィードバックコンポーネント' },
],
},
]
</script>
<template>
<!-- small -->
<lh-cascader v-model="demoCascSize" :options="options" size="small" placeholder="small" />
<!-- large -->
<lh-cascader v-model="demoCascSize2" :options="options" size="large" placeholder="large" />
<!-- 無効状態 -->
<lh-cascader v-model="demoCascDisabled" :options="options" disabled placeholder="無効状態" />
<!-- 読み取り専用 -->
<lh-cascader v-model="demoCascReadonly" :options="options" readonly placeholder="読み取り専用" />
<!-- カスタムプレースホルダー -->
<lh-cascader v-model="demoCascPlaceholder" :options="options" placeholder="カスタムプレースホルダー" />
<!-- クリア不可 -->
<lh-cascader v-model="demoCascNoClear" :options="options" :clearable="false" placeholder="クリア不可" />
</template>vue
<script>
export default {
data() {
return {
demoCascSize: [],
demoCascSize2: [],
demoCascDisabled: [],
demoCascReadonly: [],
demoCascPlaceholder: [],
demoCascNoClear: [],
options: [
{
value: 'zhinan',
label: 'ガイド',
children: [
{ value: 'sheji', label: 'デザインガイド' },
{ value: 'shejiguize', label: 'デザインルール' },
],
},
{
value: 'zujian',
label: 'コンポーネント',
children: [
{ value: 'jiben', label: '基本コンポーネント' },
{ value: 'fankui', label: 'フィードバックコンポーネント' },
],
},
],
}
},
}
</script>
<template>
<!-- small -->
<lh-cascader v-model="demoCascSize" :options="options" size="small" placeholder="small" />
<!-- large -->
<lh-cascader v-model="demoCascSize2" :options="options" size="large" placeholder="large" />
<!-- 無効状態 -->
<lh-cascader v-model="demoCascDisabled" :options="options" disabled placeholder="無効状態" />
<!-- 読み取り専用 -->
<lh-cascader v-model="demoCascReadonly" :options="options" readonly placeholder="読み取り専用" />
<!-- カスタムプレースホルダー -->
<lh-cascader v-model="demoCascPlaceholder" :options="options" placeholder="カスタムプレースホルダー" />
<!-- クリア不可 -->
<lh-cascader v-model="demoCascNoClear" :options="options" :clearable="false" placeholder="クリア不可" />
</template>パス表示と検索
show-all-levelsは入力ボックスに完全なパスを表示するかどうかを制御します(デフォルトtrue。オフにすると末尾の階層名のみ表示);separatorはパスの区切り文字をカスタマイズします。検索結果パネルにも同じものが適用されます;emit-pathをfalseに設定するとv-modelは末尾のノードの値のみバインドします。入力ボックスは完全なパスを表示し続けます;check-strictlyは任意の階層のノードを選択可能にします(任意の階層をクリックすると直接選択され、子階層の閲覧はホバーでの展開に依存します);filterableで検索を有効にします。キーワードを入力すると完全なパスで一致項目を表示します;collapse-tagsは複数選択モードでタグを折りたたみます;cascadingで親子ノードの連動チェックをオフにします;item-configでノードのフィールドエイリアスをカスタマイズします(例:id/nameでツリーを構築)。パス表示にも同じものが適用されます。
以下の例はすべて選択値をあらかじめ設定しているため、階層を順にクリックしなくても違いを比較できます。完全なパスは 浙江省/杭州市/西湖区 と表示され、show-all-levels をオフにすると 西湖区 のみ表示され、separator=" > " の場合は 浙江省 > 杭州市 > 西湖区 と表示されます。
パス表示と検索
vue
<script setup lang="ts">
import { ref } from 'vue'
const demoCascFullPath = ref(['zhejiang', 'hangzhou', 'xihu'])
const demoCascAllLevels = ref(['zhejiang', 'hangzhou', 'xihu'])
const demoCascSep = ref(['zhejiang', 'hangzhou', 'xihu'])
const demoCascEmit = ref(['xihu'])
const demoCascStrict = ref(['zhejiang', 'hangzhou'])
const demoCascFilter = ref([])
const demoCascCollapse = ref(['xihu', 'haishu'])
const demoCascLoose = ref(['xihu', 'binjiang'])
const demoCascItem = ref(['zhejiang', 'hangzhou', 'xihu'])
const pathOptions = [
{
value: 'zhejiang',
label: '浙江省',
children: [
{
value: 'hangzhou',
label: '杭州市',
children: [
{ value: 'xihu', label: '西湖区' },
{ value: 'binjiang', label: '浜江区' },
],
},
{
value: 'ningbo',
label: '寧波市',
children: [{ value: 'haishu', label: '海曙区' }],
},
],
},
{
value: 'jiangsu',
label: '江蘇省',
children: [
{
value: 'nanjing',
label: '南京市',
children: [{ value: 'xuanwu', label: '玄武区' }],
},
],
},
]
const aliasedOptions = [
{
id: 'zhejiang',
name: '浙江省',
sub: [
{
id: 'hangzhou',
name: '杭州市',
sub: [
{ id: 'xihu', name: '西湖区' },
{ id: 'binjiang', name: '浜江区' },
],
},
{
id: 'ningbo',
name: '寧波市',
sub: [{ id: 'haishu', name: '海曙区' }],
},
],
},
]
</script>
<template>
<!-- 完全なパス(デフォルト) -->
<lh-cascader v-model="demoCascFullPath" :options="pathOptions" placeholder="完全なパス(デフォルト)" />
<!-- 末尾のみ表示 -->
<lh-cascader v-model="demoCascAllLevels" :options="pathOptions" :show-all-levels="false" placeholder="末尾のみ表示" />
<!-- 区切り文字 > -->
<lh-cascader v-model="demoCascSep" :options="pathOptions" separator=" > " placeholder="区切り文字 >" />
<!-- 末尾の値のみ返す -->
<lh-cascader v-model="demoCascEmit" :options="pathOptions" :emit-path="false" placeholder="末尾の値のみ返す" />
<!-- 任意の階層を選択可能 -->
<lh-cascader v-model="demoCascStrict" :options="pathOptions" check-strictly placeholder="任意の階層を選択可能" />
<!-- 検索可能 -->
<lh-cascader v-model="demoCascFilter" :options="pathOptions" filterable placeholder="検索可能" />
<!-- 複数選択のタグ折りたたみ -->
<lh-cascader v-model="demoCascCollapse" :options="pathOptions" multiple collapse-tags placeholder="複数選択のタグ折りたたみ" />
<!-- 親子で連動しない -->
<lh-cascader v-model="demoCascLoose" :options="pathOptions" multiple :cascading="false" placeholder="親子で連動しない" />
<!-- フィールドエイリアス -->
<lh-cascader v-model="demoCascItem" :options="aliasedOptions" :item-config="{ value: 'id', label: 'name', children: 'sub' }" placeholder="フィールドエイリアス" />
</template>vue
<script>
export default {
data() {
return {
demoCascFullPath: ['zhejiang', 'hangzhou', 'xihu'],
demoCascAllLevels: ['zhejiang', 'hangzhou', 'xihu'],
demoCascSep: ['zhejiang', 'hangzhou', 'xihu'],
demoCascEmit: ['xihu'],
demoCascStrict: ['zhejiang', 'hangzhou'],
demoCascFilter: [],
demoCascCollapse: ['xihu', 'haishu'],
demoCascLoose: ['xihu', 'binjiang'],
demoCascItem: ['zhejiang', 'hangzhou', 'xihu'],
pathOptions: [
{
value: 'zhejiang',
label: '浙江省',
children: [
{
value: 'hangzhou',
label: '杭州市',
children: [
{ value: 'xihu', label: '西湖区' },
{ value: 'binjiang', label: '浜江区' },
],
},
{
value: 'ningbo',
label: '寧波市',
children: [{ value: 'haishu', label: '海曙区' }],
},
],
},
{
value: 'jiangsu',
label: '江蘇省',
children: [
{
value: 'nanjing',
label: '南京市',
children: [{ value: 'xuanwu', label: '玄武区' }],
},
],
},
],
aliasedOptions: [
{
id: 'zhejiang',
name: '浙江省',
sub: [
{
id: 'hangzhou',
name: '杭州市',
sub: [
{ id: 'xihu', name: '西湖区' },
{ id: 'binjiang', name: '浜江区' },
],
},
{
id: 'ningbo',
name: '寧波市',
sub: [{ id: 'haishu', name: '海曙区' }],
},
],
},
],
}
},
}
</script>
<template>
<!-- 完全なパス(デフォルト) -->
<lh-cascader v-model="demoCascFullPath" :options="pathOptions" placeholder="完全なパス(デフォルト)" />
<!-- 末尾のみ表示 -->
<lh-cascader v-model="demoCascAllLevels" :options="pathOptions" :show-all-levels="false" placeholder="末尾のみ表示" />
<!-- 区切り文字 > -->
<lh-cascader v-model="demoCascSep" :options="pathOptions" separator=" > " placeholder="区切り文字 >" />
<!-- 末尾の値のみ返す -->
<lh-cascader v-model="demoCascEmit" :options="pathOptions" :emit-path="false" placeholder="末尾の値のみ返す" />
<!-- 任意の階層を選択可能 -->
<lh-cascader v-model="demoCascStrict" :options="pathOptions" check-strictly placeholder="任意の階層を選択可能" />
<!-- 検索可能 -->
<lh-cascader v-model="demoCascFilter" :options="pathOptions" filterable placeholder="検索可能" />
<!-- 複数選択のタグ折りたたみ -->
<lh-cascader v-model="demoCascCollapse" :options="pathOptions" multiple collapse-tags placeholder="複数選択のタグ折りたたみ" />
<!-- 親子で連動しない -->
<lh-cascader v-model="demoCascLoose" :options="pathOptions" multiple :cascading="false" placeholder="親子で連動しない" />
<!-- フィールドエイリアス -->
<lh-cascader v-model="demoCascItem" :options="aliasedOptions" :item-config="{ value: 'id', label: 'name', children: 'sub' }" placeholder="フィールドエイリアス" />
</template>Props
| プロパティ | 説明 | 型 | デフォルト値 |
|---|---|---|---|
| modelValue | バインド値 | (string | number)[] | () => [] |
| options | オプションのリスト | [LhCascaderNode](#type-LhCascaderNode)[] | () => [] |
| size | サイズ | "small" | "medium" | "large" | "mini" | "x-large" | 'medium' |
| disabled | 無効にするかどうか | boolean | false |
| clearable | クリア可能にするかどうか | boolean | true |
| placeholder | プレースホルダー(未指定時は言語パック cascader.placeholder。中国語では「请选择」) | string | '' |
| readonly | 読み取り専用にするかどうか | boolean | false |
| showAllLevels | 入力ボックスに完全なパスを表示するかどうか | boolean | true |
| checkStrictly | 任意の階層のノードを選択可能にするかどうか | boolean | false |
| emitPath | 返り値に完全なパスを含めるかどうか | boolean | true |
| multiple | 複数選択にするかどうか | boolean | false |
| cascading | 親子で連動させるかどうか | boolean | true |
| separator | 区切り文字 | string | '/' |
| collapseTags | 複数選択モードでタグを折りたたむかどうか | boolean | false |
| filterable | 検索可能にするかどうか | boolean | false |
| itemConfig | ノードのフィールドエイリアス | [LhCascaderItemConfig](#type-LhCascaderItemConfig) | () => ({}) |
| sx | クイックレイアウトプロパティ(例: { mt: 2, w: '50%' })。インラインスタイルに変換されてトリガーのルート要素に適用されます(ポップアップパネルには影響しません) | LhSxProps | — |
Events
| イベント名 | 説明 | コールバック |
|---|---|---|
| change | 選択値が変化したときに発火します | (value: (string | number)[], path: LhCascaderNode[] | null) |
| update:model-value | バインド値が変化したときに発火します | value: (string | number)[] |
データ構造
LhCascaderNode の型定義:
ts
interface LhCascaderNode {
value: string | number
label: string
disabled?: boolean
leaf?: boolean
children?: LhCascaderNode[]
}型定義
このコンポーネントが外部にエクスポートする TypeScript の型構造を以下に示します(packages/components/cascader/src/types.ts および @lh-ui/share/core/* のソースから自動抽出。各エントリーをクリックすると完全な定義が表示されます。プロパティの説明は上の Props 表を参照してください):
LhCascaderProps
ts
export interface LhCascaderProps {
modelValue?: (string | number)[]
options?: LhCascaderNode[]
size?: LhComponentSize
disabled?: boolean
clearable?: boolean
placeholder?: string
readonly?: boolean
showAllLevels?: boolean
checkStrictly?: boolean
emitPath?: boolean
multiple?: boolean
cascading?: boolean
separator?: string
collapseTags?: boolean
filterable?: boolean
itemConfig?: LhCascaderItemConfig
/** sx クイックレイアウトプロパティ */
sx?: LhSxProps
}LhCascaderItemConfig (@lh-ui/share/core/cascader より)
ts
/**
* Cascader props の item 属性のマッピング
*/
export interface LhCascaderItemConfig {
value?: string
label?: string
children?: string
disabled?: string
leaf?: string
}LhCascaderNode (@lh-ui/share/core/cascader より)
ts
/**
* Cascader ノード
*/
export interface LhCascaderNode {
value: string | number
label: string
disabled?: boolean
leaf?: boolean
children?: LhCascaderNode[]
}LhComponentSize (@lh-ui/share/core/shared より)
ts
export type LhComponentSize = (typeof LH_SIZE_CONST)[keyof typeof LH_SIZE_CONST]Slots
| スロット | 説明 | デフォルト内容 |
|---|---|---|
| no-match | フィルターの一致結果がないときに検索パネルに表示するカスタム内容 | 言語パック cascader.noMatch(中国語では「无匹配数据」) |