Skip to content
RTL Support: Full
Accessibility: Work in progress
Translations: Not Needed

TreeSelect

TreeSelect component for selecting values from hierarchical tree data structures. It supports single and multiple selection, cascading, filtering, and asynchronous data loading.

Default TreeSelect

Basic tree select with hierarchical options.


Please Select
Vue
html
<template>
  <HLTreeSelect id="tree-select-default" :options="options" :value="selectedValue" @update:value="handleChange" />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const selectedValue = ref(null)

  const options = [
    {
      label: 'Rubber Soul',
      key: 'Rubber Soul',
      children: [
        {
          label: 'Drive My Car',
          key: 'Drive My Car',
        },
        {
          label: 'Norwegian Wood',
          key: 'Norwegian Wood',
        },
      ],
    },
    {
      label: 'Let It Be',
      key: 'Let It Be Album',
      children: [
        {
          label: 'Two Of Us',
          key: 'Two Of Us',
        },
        {
          label: 'Let It Be',
          key: 'Let It Be',
        },
      ],
    },
  ]

  const handleChange = value => {
    selectedValue.value = value
  }
</script>

Size Variants

TreeSelect supports sm, md, and lg sizes. Size affects control height, internal border radius, and focus visuals.


Please Select
Please Select
Please Select
Vue
html
<template>
  <HLTreeSelect :options="options" :value="selectedValue" @update:value="handleChange" size="sm" clearable />
  <HLTreeSelect :options="options" :value="selectedValue" @update:value="handleChange" size="md" clearable />
  <HLTreeSelect :options="options" :value="selectedValue" @update:value="handleChange" size="lg" clearable />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const selectedValue = ref(null)
  const options = [
    {
      label: 'Rubber Soul',
      key: 'Rubber Soul',
      children: [
        { label: 'Drive My Car', key: 'Drive My Car' },
        { label: 'Norwegian Wood', key: 'Norwegian Wood' },
      ],
    },
    { label: 'Let It Be', key: 'Let It Be Album' },
  ]

  const handleChange = value => {
    selectedValue.value = value
  }
</script>

Multiple Selection

Enable multiple selection with the multiple prop.


Please Select
Vue
html
<template>
  <HLTreeSelect id="tree-select-multiple" :options="options" :value="multipleValue" @update:value="(val) => multipleValue = val" multiple />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const multipleValue = ref([])
  const options = [
    {
      label: 'Rubber Soul',
      key: 'Rubber Soul',
      children: [
        { label: 'Drive My Car', key: 'Drive My Car' },
        { label: 'Norwegian Wood', key: 'Norwegian Wood' },
      ],
    },
    { label: 'Let It Be', key: 'Let It Be Album' },
  ]
</script>

Filterable and Clearable

Add search functionality and clear button.


Vue
html
<template>
  <HLTreeSelect id="tree-select-filterable" :options="options" :value="selectedValue" @update:value="handleChange" filterable clearable />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const selectedValue = ref(null)
  const options = [
    {
      label: 'Rubber Soul',
      key: 'Rubber Soul',
      children: [
        { label: 'Drive My Car', key: 'Drive My Car' },
        { label: 'Norwegian Wood', key: 'Norwegian Wood' },
      ],
    },
    { label: 'Let It Be', key: 'Let It Be Album' },
  ]

  const handleChange = value => {
    selectedValue.value = value
  }
</script>

Max Tag Count

Limit the number of visible tags in multiple selection mode.


Please Select
Vue
html
<template>
  <HLTreeSelect
    id="tree-select-max-tags"
    :options="options"
    :value="multipleValue"
    @update:value="(val) => multipleValue = val"
    multiple
    :max-tag-count="4"
  />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const multipleValue = ref([])
  const options = [
    {
      label: 'Rubber Soul',
      key: 'Rubber Soul',
      children: [
        { label: 'Drive My Car', key: 'Drive My Car' },
        { label: 'Norwegian Wood', key: 'Norwegian Wood' },
      ],
    },
    { label: 'Let It Be', key: 'Let It Be Album' },
  ]
</script>

Cascade Selection

Enable cascade mode where selecting a parent automatically selects all children. This will support with checkable prop and multiple selection.


Please Select
Vue
html
<template>
  <HLTreeSelect
    id="tree-select-cascade"
    :options="options"
    :value="cascadeValue"
    @update:value="(val) => cascadeValue = val"
    multiple
    cascade
    checkable
  />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const cascadeValue = ref([])
</script>

Check Strategy

When you tick a parent in a cascading tree, the parent and all its children become checked. checkStrategy decides which of those keys are actually reported back to you — it changes the emitted value and the tags shown, never what the user is allowed to tick.

Requires checkable + cascade.

Take a "Songs" branch holding Two Of Us and Dig A Pony. Ticking the parent gives:

checkStrategyEmitted valueTags shown
'all' (default)['Songs', 'Two Of Us', 'Dig A Pony']parent + both children
'parent'['Songs']just the parent
'child'['Two Of Us', 'Dig A Pony']just the two children

Same clicks, three different payloads. Tick the "Let It Be" parent in each picker below to compare.

check-strategy="all" (default)

Please Select

check-strategy="parent"

Please Select

check-strategy="child"

Please Select
Vue
html
<template>
  <!-- Emits the parent and all its children -->
  <HLTreeSelect :options="options" :value="value" @update:value="onChange" multiple cascade checkable check-strategy="all" />

  <!-- Emits just the parent key -->
  <HLTreeSelect :options="options" :value="value" @update:value="onChange" multiple cascade checkable check-strategy="parent" />

  <!-- Emits just the leaf keys -->
  <HLTreeSelect :options="options" :value="value" @update:value="onChange" multiple cascade checkable check-strategy="child" />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const value = ref([])
  const options = [
    {
      label: 'Rubber Soul',
      key: 'Rubber Soul',
      children: [
        { label: 'Drive My Car', key: 'Drive My Car' },
        { label: 'Norwegian Wood', key: 'Norwegian Wood' },
      ],
    },
    { label: 'Let It Be', key: 'Let It Be Album' },
  ]

  const onChange = val => {
    value.value = val
  }
</script>

INFO

Pick the strategy that matches your API: 'parent' keeps the payload small when a whole branch is selected, 'child' suits backends that only accept leaf ids. A partially-checked parent is never included by 'parent' — only fully-checked ones.

Default Expand All

Expand all tree nodes by default.


Please Select
Vue
html
<template>
  <HLTreeSelect id="tree-select-expand-all" :options="options" :value="selectedValue" @update:value="handleChange" default-expand-all />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const selectedValue = ref(null)
  const options = [
    {
      label: 'Rubber Soul',
      key: 'Rubber Soul',
      children: [
        { label: 'Drive My Car', key: 'Drive My Car' },
        { label: 'Norwegian Wood', key: 'Norwegian Wood' },
      ],
    },
    { label: 'Let It Be', key: 'Let It Be Album' },
  ]

  const handleChange = value => {
    selectedValue.value = value
  }
</script>

Default Expanded Keys

Specify which nodes should be expanded by default using their keys.


Please Select
Vue
html
<template>
  <HLTreeSelect
    id="tree-select-expanded-keys"
    :options="options"
    :value="selectedValue"
    @update:value="handleChange"
    :default-expanded-keys="['Let It Be Album']"
  />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const selectedValue = ref(null)
  const options = [
    {
      label: 'Rubber Soul',
      key: 'Rubber Soul',
      children: [
        { label: 'Drive My Car', key: 'Drive My Car' },
        { label: 'Norwegian Wood', key: 'Norwegian Wood' },
      ],
    },
    { label: 'Let It Be', key: 'Let It Be Album' },
  ]

  const handleChange = value => {
    selectedValue.value = value
  }
</script>

Controlled Expanded Keys

defaultExpandedKeys (above) is uncontrolled — the tree takes it as a starting point and then manages expansion itself. To drive expansion from your own state, bind expandedKeys and handle @update:expandedKeys; without that handler the tree will not expand at all, because nothing updates the bound value.

Expanded: Rubber Soul
Please Select
Vue
html
<template>
  <div>Expanded: {{ expandedKeys.join(', ') }}</div>
  <HLTreeSelect
    id="tree-select-controlled-expanded"
    :options="options"
    :value="value"
    @update:value="(val) => value = val"
    :expanded-keys="expandedKeys"
    @update:expanded-keys="(keys) => expandedKeys = keys"
  />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const value = ref(null)
  // Bound both ways: the tree reads this, and the handler writes it back
  const expandedKeys = ref(['Rubber Soul'])
</script>

Override Default Node Click Behavior

Customize what happens when a node is clicked.Here is the example to toggle expand when a node is clicked.


Please Select
Vue
html
<template>
  <HLTreeSelect
    id="tree-select-click-behavior"
    :options="options"
    :value="selectedValue"
    @update:value="handleChange"
    :override-default-node-click-behavior="overrideDefaultNodeClickBehavior"
  />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const selectedValue = ref(null)

  const overrideDefaultNodeClickBehavior = info => {
    // If the node has children, toggle expand instead of selecting
    if (info?.option?.children?.length) {
      return 'toggleExpand'
    }
    return 'default'
  }

  const handleChange = value => {
    selectedValue.value = value
  }
</script>

Custom Slots

Customize various parts of the tree select using slots.


Please Select
html
<template>
  <HLTreeSelect id="tree-select-slots" :options="options" :value="selectedValue" @update:value="handleChange" multiple filterable>
    <!-- Pinned above the option list -->
    <template #header>
      <div class="p-2 text-sm font-medium text-gray-700">Pick one or more tracks</div>
    </template>
    <!-- Pinned below the option list -->
    <template #action>
      <div class="p-2 text-sm text-gray-600">If you click this demo, you may need it.</div>
    </template>
    <template #empty>
      <div class="p-4 text-center text-gray-500">Empty handler when options are empty</div>
    </template>
    <template #arrow>
      <Star01Icon class="w-5 h-5" />
    </template>
  </HLTreeSelect>
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { Star01Icon } from '@gohighlevel/ghl-icons/24/outline'
  import { ref } from 'vue'

  const selectedValue = ref(null)
</script>

Show Check Mark

Enable Checkmark at end of the selected option. This can be done with showCheckMark prop.


Please Select
Vue
html
<template>
  <HLTreeSelect
    id="tree-select-cascade"
    :options="options"
    :value="selectedCheckMarkValue"
    @update:value="(val) => selectedCheckMarkValue = val"
    showCheckMark
  />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const selectedCheckMarkValue = ref(null)
</script>

Render Label

Customize how labels are rendered in the tree.


Please Select
html
<template>
  <HLTreeSelect
    id="tree-select-render-label"
    :options="options"
    :value="renderLabelValue"
    @update:value="(val) => renderLabelValue = val"
    :render-label="renderLabel"
  />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { ref, h } from 'vue'

  const renderLabelValue = ref(null)

  const renderLabel = info => {
    return h(
      'div',
      {
        style: {
          display: 'flex',
          alignItems: 'center',
        },
      },
      [
        h(
          'div',
          {
            style: {
              fontWeight: 400,
              fontSize: '14px',
              lineHeight: '20px',
              padding: '12px',
            },
            class: info.selected ? 'bg-primary' : '',
          },
          [
            h(
              'p',
              {
                style: { margin: 0 },
                class: info.selected ? 'bg-primary' : '',
              },
              [info.option.label]
            ),
          ]
        ),
      ]
    )
  }
</script>

Render Tag

Customize how selected tags are rendered in multiple selection mode.


Dig A Pony
html
<template>
  <HLTreeSelect
    id="tree-select-render-tag"
    :options="options"
    :value="renderTagValue"
    @update:value="(val) => renderTagValue = val"
    :render-tag="renderTag"
    multiple
  />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { ref, h } from 'vue'

  const renderTagValue = ref(['Let It Be Album'])

  const renderTag = info => {
    return h('div', { class: 'bg-primary border border-solid border-black px-2' }, [
      info.option.label,
      h('button', { class: 'ml-2', onClick: () => info.handleClose() }, 'X'),
    ])
  }
</script>

Render Prefix

Add custom prefix content to tree nodes.


Please Select
html
<template>
  <HLTreeSelect
    id="tree-select-render-prefix"
    :options="options"
    :value="renderPrefixValue"
    @update:value="(val) => renderPrefixValue = val"
    :render-prefix="renderPrefix"
  />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { Star01Icon } from '@gohighlevel/ghl-icons/24/outline'
  import { ref, h } from 'vue'

  const renderPrefixValue = ref(null)

  const renderPrefix = info => {
    return h(Star01Icon, {
      style: {
        width: '16px',
        height: '16px',
        fill: info.checked ? 'blue' : 'none',
      },
    })
  }
</script>

Render Suffix

Add custom suffix content to tree nodes.


Please Select
html
<template>
  <HLTreeSelect
    id="tree-select-render-suffix"
    :options="options"
    :value="renderSuffixValue"
    @update:value="(val) => renderSuffixValue = val"
    :render-suffix="renderSuffix"
  />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { Star01Icon } from '@gohighlevel/ghl-icons/24/outline'
  import { ref, h } from 'vue'

  const renderSuffixValue = ref(null)

  const renderSuffix = info => {
    return h(Star01Icon, {
      style: {
        width: '16px',
        height: '16px',
        fill: info.checked ? 'blue' : 'none',
      },
    })
  }
</script>

Async Loading

Load child nodes asynchronously when expanding parent nodes.


Please Select
html
<template>
  <HLTreeSelect
    id="tree-select-async"
    :options="asyncOptions"
    :value="asyncValue"
    @update:value="(val) => asyncValue = val"
    :on-load="handleLoad"
    allow-checking-not-loaded
    multiple
    checkable
    cascade
  />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const asyncValue = ref(null)
  const asyncOptions = ref([
    {
      label: 'Rubber Soul',
      key: 'Rubber Soul',
      depth: 1,
      isLeaf: false,
    },
  ])

  const getChildren = option => {
    const children = []
    for (let i = 0; i <= option.depth; ++i) {
      children.push({
        label: option.label + '-' + i,
        key: option.label + '-' + i,
        depth: option.depth + 1,
        isLeaf: option.depth === 3,
      })
    }
    return children
  }

  const handleLoad = option => {
    return new Promise(resolve => {
      window.setTimeout(() => {
        option.children = getChildren(option)
        resolve()
      }, 1000)
    })
  }
</script>

Infinite Scroll

Paginate the top-level options as the user scrolls. The @scroll event forwards the dropdown list's raw scroll event, so you decide when to fetch the next page — detect the bottom from event.target in the handler and append the next page of options. This composes with on-load for lazy-loading each node's children on expand.

Detect the bottom with scrollTop + clientHeight >= scrollHeight - threshold. Use a small threshold (px from the bottom) to start fetching a little early, e.g. 40.

INFO

@scroll fires on every scroll event, so guard the handler: only fetch when near the bottom, skip while a request is in flight, and stop once all data is loaded (as below). This keeps a single page from being requested repeatedly.


Scroll to load more albums
html
<template>
  <HLTreeSelect
    id="tree-select-infinite"
    :options="options"
    :value="selectedValue"
    @update:value="(val) => selectedValue = val"
    @scroll="handleScroll"
    :on-load="handleLoad"
    placeholder="Scroll to load more albums"
  />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const PAGE_SIZE = 20
  const TOTAL = 80
  // px from the bottom at which to fetch the next page.
  const SCROLL_END_THRESHOLD = 40

  const selectedValue = ref(null)
  const loadedCount = ref(PAGE_SIZE)
  const isLoadingMore = ref(false)

  // A parent node is loadable (isLeaf: false) but has no children yet — they
  // arrive lazily via on-load when the node is expanded.
  const makeAlbum = i => ({ label: `Album ${i}`, key: `album-${i}`, isLeaf: false })
  const options = ref(Array.from({ length: PAGE_SIZE }, (_, i) => makeAlbum(i + 1)))

  // @scroll forwards the raw scroll event; detect the bottom yourself. Guard
  // against an in-flight request and stop once everything is loaded.
  const handleScroll = e => {
    const el = e.target
    const nearBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - SCROLL_END_THRESHOLD
    if (!nearBottom || isLoadingMore.value || loadedCount.value >= TOTAL) return
    isLoadingMore.value = true
    // Replace with your paginated API call.
    window.setTimeout(() => {
      const next = Math.min(loadedCount.value + PAGE_SIZE, TOTAL)
      for (let i = loadedCount.value; i < next; ++i) options.value.push(makeAlbum(i + 1))
      loadedCount.value = next
      isLoadingMore.value = false
    }, 600)
  }

  // Lazy-load a node's children when it is expanded.
  const handleLoad = node => {
    return new Promise(resolve => {
      window.setTimeout(() => {
        node.children = Array.from({ length: 5 }, (_, i) => ({
          label: `${node.label} — Track ${i + 1}`,
          key: `${node.key}-track-${i + 1}`,
          isLeaf: true,
        }))
        resolve()
      }, 600)
    })
  }
</script>

Placement

placement sets which side of the trigger the dropdown opens on. It accepts the four sides (top, bottom, left, right) and their -start / -end alignment variants; the default is bottom-start.

Opens upward
Vue
html
<template>
  <HLTreeSelect
    id="tree-select-placement"
    :options="options"
    :value="value"
    @update:value="onChange"
    placement="top-start"
    placeholder="Opens upward"
  />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const value = ref(null)
  const onChange = val => {
    value.value = val
  }
</script>

Consistent Menu Width

By default the dropdown matches the trigger's width, so long labels wrap or truncate. Set :consistent-menu-width="false" to let the menu size itself to its content and grow wider than the trigger — useful for deep trees whose indented labels would otherwise be cramped.

Default — menu matches the trigger width

Please Select

:consistent-menu-width="false" — menu grows to fit

Please Select
Vue
html
<template>
  <!-- Menu is locked to the trigger width (default) -->
  <HLTreeSelect :options="options" :value="value" @update:value="onChange" default-expand-all />

  <!-- Menu sizes to its content, so it can be wider than the trigger -->
  <HLTreeSelect
    :options="options"
    :value="value"
    @update:value="onChange"
    :consistent-menu-width="false"
    default-expand-all
  />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const value = ref(null)
  const options = [
    {
      label: 'Rubber Soul',
      key: 'Rubber Soul',
      children: [{ label: "Everybody's Got Something to Hide Except Me and My Monkey", key: 'long-one' }],
    },
  ]

  const onChange = val => {
    value.value = val
  }
</script>

Show Avatar in Tags

showAvatarInTags controls the avatars the component renders by default — in the dropdown labels as well as in the selected tags. It is true by default; set it to false for a plain text-only tree.

An option's src supplies the avatar image; without one, the avatar falls back to initials derived from the option's label.

Default — avatars in labels and tags

TO

Two Of Us

:show-avatar-in-tags="false" — text only

Two Of Us
Vue
html
<template>
  <!-- Avatars shown (default) -->
  <HLTreeSelect :options="options" :value="value" @update:value="onChange" multiple default-expand-all />

  <!-- Text only -->
  <HLTreeSelect
    :options="options"
    :value="value"
    @update:value="onChange"
    multiple
    :show-avatar-in-tags="false"
    default-expand-all
  />
</template>

<script setup>
  import { HLTreeSelect } from '@platform-ui/highrise'
  import { ref } from 'vue'

  const value = ref(['Two Of Us'])
  const options = [
    {
      label: 'Rubber Soul',
      key: 'Rubber Soul',
      // `src` supplies the avatar image; without it the avatar shows initials
      src: 'https://picsum.photos/seed/FeB6P/640/480',
      children: [{ label: 'Drive My Car', key: 'Drive My Car' }],
    },
    {
      label: 'Let It Be',
      key: 'Let It Be Album',
      children: [{ label: 'Two Of Us', key: 'Two Of Us' }],
    },
  ]

  const onChange = val => {
    value.value = val
  }
</script>

INFO

showAvatarInTags only affects the component's built-in rendering. A custom renderLabel or renderTag replaces that rendering entirely, so the avatar is then yours to draw (or omit).

Empty Data

Render an empty state by passing an empty options array. The built-in empty indicator renders inside the menu panel; the trigger remains interactive so users can still blur or retry.

No options available
html
<template>
  <HLTreeSelect id="tree-select-empty" :options="[]" placeholder="No options available" />
</template>

Loading State

Use the loading prop to show the in-panel loading indicator. Combine with an empty options array when you have no cached data, or leave the previous options in place to avoid content shift during async refresh.

Loading options...
html
<template>
  <HLTreeSelect
    id="tree-select-loading"
    :options="[]"
    :loading="true"
    placeholder="Loading options..."
  />
</template>

Error State

Set status="error" to apply the error-toned border and focus-ring tokens. Pair with HLFormItem validationStatus="error" + feedback so assistive tech announces the failure through aria-invalid + aria-describedby.

Failed to load options
html
<template>
  <HLTreeSelect
    id="tree-select-error"
    :options="[]"
    status="error"
    placeholder="Failed to load options"
  />
</template>

Imports


ts
import { HLTreeSelect } from '@platform-ui/highrise'

Props

PropTypeDefaultDescription
id *stringundefinedUnique identifier for the tree select
allowCheckingNotLoadedbooleanfalseAllow checking nodes that haven't been loaded yet (for async loading)
cascadebooleanfalseWhether to cascade selection to child nodes
checkablebooleanfalseShow checkboxes for nodes
checkStrategy'all' | 'parent' | 'child''all'Strategy for what values are shown when cascading: 'all' shows all checked nodes, 'parent' shows only parent nodes, 'child' shows only leaf nodes
clearablebooleanfalseShow clear button
consistentMenuWidthbooleantrueWhether dropdown menu width matches the select width
defaultExpandAllbooleanfalseExpand all nodes by default
defaultExpandedKeysArray<string | number>[]Keys of nodes that should be expanded by default
disabledbooleanfalseDisable the tree select
expandedKeysArray<string | number>undefinedControlled expanded keys (requires @update:expandedKeys handler)
filterablebooleanfalseEnable search/filter functionality
loadingbooleanfalseShow loading state
maxTagCountnumber | 'responsive''responsive'Maximum number of visible tags in multiple mode
multiplebooleanfalseEnable multiple selection
onLoad(node: TreeSelectOption) => Promise<void>undefinedAsync function to load child nodes
optionsTreeSelectOption[][]Tree data options
overrideDefaultNodeClickBehavior(info: { option: TreeSelectOption }) => ClickBehaviourTypeundefinedOverride default click behavior for nodes
placeholderstring'Please Select'Placeholder text
placementFollowerPlacement'bottom-start'Dropdown placement
renderLabel(info: { option: TreeSelectOption; checked: boolean; selected: boolean }) => VNodeChildundefinedCustom label render function
renderPrefix(info: { option: TreeSelectOption; checked: boolean; selected: boolean }) => VNodeChildundefinedCustom prefix render function
renderSuffix(info: { option: TreeSelectOption; checked: boolean; selected: boolean }) => VNodeChildundefinedCustom suffix render function
renderTag(info: { option: TreeSelectOption; handleClose: () => void }) => VNodeChildundefinedCustom tag render function
showbooleanundefinedControl dropdown visibility
showAvatarInTagsbooleantrueShow the default avatar in dropdown labels and in selected tags. Ignored where a custom renderLabel / renderTag takes over
size'sm' | 'md' | 'lg''md'Size of the tree select
status'success' | 'warning' | 'error'undefinedValidation status
valuestring | number | Array<string | number> | nullundefinedSelected value(s)
showCheckMarkbooleanfalseShow check mark icon in checked nodes
tostring | HTMLElement | falseundefinedTeleport target for the dropdown menu. Pass a CSS selector or HTMLElement to mount the menu inside a specific container. Pass false to disable teleporting.

TreeSelectOption

  • Always provide unique key values for each node to ensure proper tracking and updates.
HLTreeSelectOption.ts
ts
interface HLTreeSelectOption {
  key: string | number // Unique identifier for the node
  label: string // Display text for the node
  description?: string // Optional description text
  src?: string // Optional image source (e.g., for avatars)
  children?: TreeSelectOption[] // Child nodes
  disabled?: boolean // Whether the node is disabled
  isLeaf?: boolean // Indicates if the node is a leaf (no children, used in async loading)
  depth?: number // Depth level (used in async loading)
  renderOption?: () => VNodeChild // Custom render function for the option
  [key: string]: any // Additional custom properties
}

Emits

EventParametersDescription
@update:value(value: string | number | Array<string | number>, option: TreeSelectOption | TreeSelectOption[], meta: { node: TreeSelectOption, action: string })Emitted when selection changes
@update:expandedKeys(keys: Array<string | number>, meta: { node: TreeSelectOption, action: string })Emitted when expanded keys change
@scroll(e: Event)Emitted on the dropdown list's native scroll event. Detect the bottom from e.target for infinite-scroll / pagination of top-level options

Slots

NameParametersDescription
action()Footer content in the dropdown
arrow()Custom arrow icon
empty()Content shown when there are no options
header()Header content in the dropdown