Skip to content
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>

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 = [
    // ... options data
  ]
</script>

Filterable and Clearable

Add search functionality and clear button.


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

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>

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>

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>

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>

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>
    <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>

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>

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 avatar in tags for multiple selection
size'sm' | 'md' | 'lg''md'Size of the tree select
status'success' | 'warning' | 'error'undefinedValidation status
valuestring | number | Array<string | number> | nullundefinedSelected value(s)

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

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