Skip to content

Select Component ​

Overview ​

The Select component is a dropdown selection component used to choose from multiple options. It supports single selection, multiple selection, search, remote search, grouping, and many other features, making it one of the most commonly used components in forms.

Learning Objectives ​

  • Master the basic concepts and use cases of Select
  • Learn how to use basic selectors
  • Understand the difference between single and multiple selection modes
  • Master state control and event handling of selectors
  • Learn to use option grouping and custom templates
  • Understand remote search and large data handling
  • Master the complete usage of the API

Basic Usage ​

Basic Selector ​

The simplest selector usage:

vue
<template>
  <div>
    <el-select v-model="value" placeholder="Please select">
      <el-option
        v-for="item in options"
        :key="item.value"
        :label="item.label"
        :value="item.value"
      />
    </el-select>
    <p>Selected value: {{ value }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const value = ref('')
const options = [
  { value: 'option1', label: 'Option 1' },
  { value: 'option2', label: 'Option 2' },
  { value: 'option3', label: 'Option 3' },
  { value: 'option4', label: 'Option 4' }
]
</script>

Disabled State ​

Disable the selector or options using the disabled attribute:

vue
<template>
  <div>
    <h4>Disabled Selector</h4>
    <el-select v-model="value1" disabled placeholder="Please select">
      <el-option
        v-for="item in options"
        :key="item.value"
        :label="item.label"
        :value="item.value"
      />
    </el-select>
    
    <h4>Disabled Options</h4>
    <el-select v-model="value2" placeholder="Please select">
      <el-option
        v-for="item in options"
        :key="item.value"
        :label="item.label"
        :value="item.value"
        :disabled="item.disabled"
      />
    </el-select>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const value1 = ref('')
const value2 = ref('')
const options = [
  { value: 'option1', label: 'Option 1' },
  { value: 'option2', label: 'Option 2', disabled: true },
  { value: 'option3', label: 'Option 3' },
  { value: 'option4', label: 'Option 4', disabled: true }
]
</script>

Clearable ​

Enable clear functionality using the clearable attribute:

vue
<template>
  <div>
    <el-select v-model="value" clearable placeholder="Please select">
      <el-option
        v-for="item in options"
        :key="item.value"
        :label="item.label"
        :value="item.value"
      />
    </el-select>
    <p>Selected value: {{ value }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const value = ref('')
const options = [
  { value: 'option1', label: 'Option 1' },
  { value: 'option2', label: 'Option 2' },
  { value: 'option3', label: 'Option 3' },
  { value: 'option4', label: 'Option 4' }
]
</script>

Multiple Selection Mode ​

Basic Multiple Selection ​

Enable multiple selection mode using the multiple attribute:

vue
<template>
  <div>
    <el-select
      v-model="value"
      multiple
      placeholder="Please select"
      style="width: 240px"
    >
      <el-option
        v-for="item in options"
        :key="item.value"
        :label="item.label"
        :value="item.value"
      />
    </el-select>
    <p>Selected values: {{ value }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const value = ref([])
const options = [
  { value: 'option1', label: 'Option 1' },
  { value: 'option2', label: 'Option 2' },
  { value: 'option3', label: 'Option 3' },
  { value: 'option4', label: 'Option 4' },
  { value: 'option5', label: 'Option 5' }
]
</script>

Collapsed Tags ​

Use collapse-tags and collapse-tags-tooltip to collapse multiple selection tags:

vue
<template>
  <div>
    <h4>Collapsed Tags</h4>
    <el-select
      v-model="value1"
      multiple
      collapse-tags
      placeholder="Please select"
      style="width: 240px"
    >
      <el-option
        v-for="item in options"
        :key="item.value"
        :label="item.label"
        :value="item.value"
      />
    </el-select>
    
    <h4>Collapsed Tags + Tooltip</h4>
    <el-select
      v-model="value2"
      multiple
      collapse-tags
      collapse-tags-tooltip
      placeholder="Please select"
      style="width: 240px"
    >
      <el-option
        v-for="item in options"
        :key="item.value"
        :label="item.label"
        :value="item.value"
      />
    </el-select>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const value1 = ref(['option1', 'option2', 'option3'])
const value2 = ref(['option1', 'option2', 'option3', 'option4'])
const options = [
  { value: 'option1', label: 'Option 1' },
  { value: 'option2', label: 'Option 2' },
  { value: 'option3', label: 'Option 3' },
  { value: 'option4', label: 'Option 4' },
  { value: 'option5', label: 'Option 5' }
]
</script>

Searchable ​

Enable search functionality using the filterable attribute:

vue
<template>
  <div>
    <el-select
      v-model="value"
      filterable
      placeholder="Please select or search"
    >
      <el-option
        v-for="item in options"
        :key="item.value"
        :label="item.label"
        :value="item.value"
      />
    </el-select>
    <p>Selected value: {{ value }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const value = ref('')
const options = [
  { value: 'beijing', label: 'Beijing' },
  { value: 'shanghai', label: 'Shanghai' },
  { value: 'guangzhou', label: 'Guangzhou' },
  { value: 'shenzhen', label: 'Shenzhen' },
  { value: 'hangzhou', label: 'Hangzhou' },
  { value: 'nanjing', label: 'Nanjing' },
  { value: 'chengdu', label: 'Chengdu' },
  { value: 'wuhan', label: 'Wuhan' }
]
</script>

Implement remote search using remote and remote-method:

vue
<template>
  <div>
    <el-select
      v-model="value"
      filterable
      remote
      reserve-keyword
      placeholder="Please enter keyword"
      :remote-method="remoteMethod"
      :loading="loading"
    >
      <el-option
        v-for="item in options"
        :key="item.value"
        :label="item.label"
        :value="item.value"
      />
    </el-select>
    <p>Selected value: {{ value }}</p>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'

const value = ref('')
const options = ref([])
const loading = ref(false)

const list = [
  { value: 'Alabama', label: 'Alabama' },
  { value: 'Alaska', label: 'Alaska' },
  { value: 'Arizona', label: 'Arizona' },
  { value: 'Arkansas', label: 'Arkansas' },
  { value: 'California', label: 'California' },
  { value: 'Colorado', label: 'Colorado' },
  { value: 'Connecticut', label: 'Connecticut' },
  { value: 'Delaware', label: 'Delaware' },
  { value: 'Florida', label: 'Florida' },
  { value: 'Georgia', label: 'Georgia' }
]

const remoteMethod = (query) => {
  if (query) {
    loading.value = true
    setTimeout(() => {
      loading.value = false
      options.value = list.filter(item => {
        return item.label.toLowerCase().includes(query.toLowerCase())
      })
    }, 200)
  } else {
    options.value = []
  }
}

onMounted(() => {
  options.value = list
})
</script>

Option Grouping ​

Use el-option-group to group options:

vue
<template>
  <div>
    <el-select v-model="value" placeholder="Please select">
      <el-option-group
        v-for="group in options"
        :key="group.label"
        :label="group.label"
      >
        <el-option
          v-for="item in group.options"
          :key="item.value"
          :label="item.label"
          :value="item.value"
        />
      </el-option-group>
    </el-select>
    <p>Selected value: {{ value }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const value = ref('')
const options = [
  {
    label: 'Popular Cities',
    options: [
      { value: 'beijing', label: 'Beijing' },
      { value: 'shanghai', label: 'Shanghai' },
      { value: 'guangzhou', label: 'Guangzhou' },
      { value: 'shenzhen', label: 'Shenzhen' }
    ]
  },
  {
    label: 'Other Cities',
    options: [
      { value: 'hangzhou', label: 'Hangzhou' },
      { value: 'nanjing', label: 'Nanjing' },
      { value: 'chengdu', label: 'Chengdu' },
      { value: 'wuhan', label: 'Wuhan' }
    ]
  }
]
</script>

Custom Templates ​

Custom Option Content ​

Use slots to customize option display content:

vue
<template>
  <div>
    <el-select v-model="value" placeholder="Please select">
      <el-option
        v-for="item in cities"
        :key="item.value"
        :label="item.label"
        :value="item.value"
      >
        <span style="float: left">{{ item.label }}</span>
        <span style="float: right; color: #8492a6; font-size: 13px">
          {{ item.desc }}
        </span>
      </el-option>
    </el-select>
    <p>Selected value: {{ value }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const value = ref('')
const cities = [
  {
    value: 'beijing',
    label: 'Beijing',
    desc: 'Capital of China'
  },
  {
    value: 'shanghai',
    label: 'Shanghai',
    desc: 'Magic City'
  },
  {
    value: 'guangzhou',
    label: 'Guangzhou',
    desc: 'Flower City'
  },
  {
    value: 'shenzhen',
    label: 'Shenzhen',
    desc: 'Tech City'
  }
]
</script>

Custom Prefix and Suffix ​

Use prefix and suffix slots:

vue
<template>
  <div>
    <el-select v-model="value" placeholder="Please select">
      <template #prefix>
        <el-icon><Location /></el-icon>
      </template>
      <el-option
        v-for="item in options"
        :key="item.value"
        :label="item.label"
        :value="item.value"
      />
    </el-select>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { Location } from '@element-plus/icons-vue'

const value = ref('')
const options = [
  { value: 'option1', label: 'Option 1' },
  { value: 'option2', label: 'Option 2' },
  { value: 'option3', label: 'Option 3' }
]
</script>

Sizes ​

Use the size attribute to set the selector size:

vue
<template>
  <div>
    <h4>Large Size</h4>
    <el-select v-model="value1" size="large" placeholder="Please select">
      <el-option
        v-for="item in options"
        :key="item.value"
        :label="item.label"
        :value="item.value"
      />
    </el-select>
    
    <h4>Default Size</h4>
    <el-select v-model="value2" placeholder="Please select">
      <el-option
        v-for="item in options"
        :key="item.value"
        :label="item.label"
        :value="item.value"
      />
    </el-select>
    
    <h4>Small Size</h4>
    <el-select v-model="value3" size="small" placeholder="Please select">
      <el-option
        v-for="item in options"
        :key="item.value"
        :label="item.label"
        :value="item.value"
      />
    </el-select>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const value1 = ref('')
const value2 = ref('')
const value3 = ref('')
const options = [
  { value: 'option1', label: 'Option 1' },
  { value: 'option2', label: 'Option 2' },
  { value: 'option3', label: 'Option 3' }
]
</script>

Practical Application Examples ​

User Information Selector ​

vue
<template>
  <div class="user-selector">
    <h3>User Selector</h3>
    
    <div class="selector-group">
      <div class="selector-item">
        <label>Select User:</label>
        <el-select
          v-model="selectedUser"
          filterable
          remote
          reserve-keyword
          placeholder="Enter username to search"
          :remote-method="searchUsers"
          :loading="loading"
          @change="handleUserChange"
        >
          <el-option
            v-for="user in users"
            :key="user.id"
            :label="user.name"
            :value="user.id"
          >
            <div class="user-option">
              <img :src="user.avatar" class="user-avatar" />
              <div class="user-info">
                <div class="user-name">{{ user.name }}</div>
                <div class="user-email">{{ user.email }}</div>
              </div>
            </div>
          </el-option>
        </el-select>
      </div>
      
      <div class="selector-item">
        <label>Select Department:</label>
        <el-select
          v-model="selectedDepartment"
          placeholder="Please select department"
          @change="handleDepartmentChange"
        >
          <el-option-group
            v-for="group in departments"
            :key="group.label"
            :label="group.label"
          >
            <el-option
              v-for="dept in group.departments"
              :key="dept.id"
              :label="dept.name"
              :value="dept.id"
            />
          </el-option-group>
        </el-select>
      </div>
      
      <div class="selector-item">
        <label>Select Roles:</label>
        <el-select
          v-model="selectedRoles"
          multiple
          collapse-tags
          collapse-tags-tooltip
          placeholder="Please select roles"
        >
          <el-option
            v-for="role in roles"
            :key="role.id"
            :label="role.name"
            :value="role.id"
            :disabled="role.disabled"
          >
            <span>{{ role.name }}</span>
            <span class="role-desc">{{ role.description }}</span>
          </el-option>
        </el-select>
      </div>
    </div>
    
    <div class="selection-summary">
      <h4>Selection Results</h4>
      <p>User: {{ getUserName(selectedUser) }}</p>
      <p>Department: {{ getDepartmentName(selectedDepartment) }}</p>
      <p>Roles: {{ getRoleNames(selectedRoles) }}</p>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive } from 'vue'
import { ElMessage } from 'element-plus'

const selectedUser = ref('')
const selectedDepartment = ref('')
const selectedRoles = ref([])
const loading = ref(false)
const users = ref([])

const allUsers = [
  {
    id: 1,
    name: 'John Smith',
    email: 'john@example.com',
    avatar: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png'
  },
  {
    id: 2,
    name: 'Jane Doe',
    email: 'jane@example.com',
    avatar: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png'
  },
  {
    id: 3,
    name: 'Bob Johnson',
    email: 'bob@example.com',
    avatar: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png'
  }
]

const departments = [
  {
    label: 'Technical Departments',
    departments: [
      { id: 1, name: 'Frontend Development' },
      { id: 2, name: 'Backend Development' },
      { id: 3, name: 'QA Testing' }
    ]
  },
  {
    label: 'Business Departments',
    departments: [
      { id: 4, name: 'Product Management' },
      { id: 5, name: 'Operations' },
      { id: 6, name: 'Sales' }
    ]
  }
]

const roles = [
  { id: 1, name: 'Administrator', description: 'System admin privileges' },
  { id: 2, name: 'Developer', description: 'Development privileges' },
  { id: 3, name: 'Tester', description: 'Testing privileges' },
  { id: 4, name: 'Guest', description: 'Read-only privileges', disabled: true }
]

const searchUsers = (query) => {
  if (query) {
    loading.value = true
    setTimeout(() => {
      loading.value = false
      users.value = allUsers.filter(user => {
        return user.name.toLowerCase().includes(query.toLowerCase()) ||
               user.email.toLowerCase().includes(query.toLowerCase())
      })
    }, 200)
  } else {
    users.value = allUsers
  }
}

const handleUserChange = (value) => {
  ElMessage.success(`Selected user: ${getUserName(value)}`)
}

const handleDepartmentChange = (value) => {
  ElMessage.success(`Selected department: ${getDepartmentName(value)}`)
}

const getUserName = (userId) => {
  const user = allUsers.find(u => u.id === userId)
  return user ? user.name : 'Not selected'
}

const getDepartmentName = (deptId) => {
  for (const group of departments) {
    const dept = group.departments.find(d => d.id === deptId)
    if (dept) return dept.name
  }
  return 'Not selected'
}

const getRoleNames = (roleIds) => {
  if (!roleIds.length) return 'Not selected'
  return roleIds.map(id => {
    const role = roles.find(r => r.id === id)
    return role ? role.name : ''
  }).filter(Boolean).join(', ')
}

// Initialize user list
users.value = allUsers
</script>

<style scoped>
.user-selector {
  max-width: 800px;
  padding: 20px;
  border: 1px solid #dcdfe6;
  border-radius: 8px;
}

.selector-group {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.selector-item {
  display: flex;
  align-items: center;
  gap: 12px;
}

.selector-item label {
  width: 100px;
  font-weight: 500;
}

.selector-item .el-select {
  flex: 1;
  max-width: 300px;
}

.user-option {
  display: flex;
  align-items: center;
  gap: 8px;
}

.user-avatar {
  width: 24px;
  height: 24px;
  border-radius: 50%;
}

.user-info {
  flex: 1;
}

.user-name {
  font-weight: 500;
  color: #303133;
}

.user-email {
  font-size: 12px;
  color: #909399;
}

.role-desc {
  float: right;
  color: #8492a6;
  font-size: 12px;
}

.selection-summary {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid #e4e7ed;
}

.selection-summary h4 {
  margin-bottom: 12px;
  color: #303133;
}

.selection-summary p {
  margin: 4px 0;
  color: #606266;
}
</style>

API Reference ​

Select Attributes ​

NameDescriptionTypeDefault
model-value / v-modelBinding valuestring / number / boolean / object / array—
multipleWhether multiple-select is activatedbooleanfalse
disabledWhether Select is disabledbooleanfalse
value-keyUnique identity key name for value, required when value is an objectstringvalue
sizeSize of Inputenum—
clearableWhether select can be clearedbooleanfalse
collapse-tagsWhether to collapse tags to a text when multiple selectingbooleanfalse
collapse-tags-tooltipWhether show all selected tags in tooltip when mouse hover collapsed tagsbooleanfalse
multiple-limitMaximum number of options user can select when multiple is true. No limit when set to 0number0
nameThe name attribute of select inputstring—
effectTooltip theme, built-in theme: dark / lightenumlight
autocompleteThe autocomplete attribute of select inputstringoff
placeholderPlaceholderstringPlease select
filterableWhether Select is filterablebooleanfalse
allow-createWhether creating new items is allowed. To use this, filterable must be truebooleanfalse
filter-methodCustom filter methodfunction—
remoteWhether options are loaded from serverbooleanfalse
remote-methodCustom remote search methodfunction—
remote-show-suffixWhether to show suffix icon in remote searchbooleanfalse
loadingWhether Select is loading data from serverbooleanfalse
loading-textDisplayed text while loading data from serverstringLoading
no-match-textDisplayed text when no data matches the filtering querystringNo matching data
no-data-textDisplayed text when there is no optionsstringNo data
popper-classCustom class name for Select's dropdownstring—
reserve-keywordWhen multiple and filterable is true, whether to reserve current keyword after selecting an optionbooleantrue
default-first-optionSelect first matching option on enter key. Use with filterable or remotebooleanfalse
teleportedWhether select dropdown is teleported to the bodybooleantrue
persistentWhen select dropdown is inactive and persistent is false, select dropdown will be destroyedbooleantrue
automatic-dropdownFor non-filterable Select, this prop decides if the option menu pops up when the input is focusedbooleanfalse
clear-iconCustom clear icon componentstring / ComponentCircleClose
fit-input-widthWhether the width of the dropdown is the same as the inputbooleanfalse
suffix-iconCustom suffix icon componentstring / ComponentArrowDown
tag-typeTag typeenuminfo
validate-eventWhether to trigger form validationbooleantrue
placementPosition of dropdownenumbottom-start

Select Events ​

NameDescriptionType
changeTriggers when the selected value changesFunction
visible-changeTriggers when the dropdown appears/disappearsFunction
remove-tagTriggers when a tag is removed in multiple modeFunction
clearTriggers when the clear icon is clicked in a clearable SelectFunction
blurTriggers when Input blursFunction
focusTriggers when Input focusesFunction

Select Slots ​

NameDescriptionSubtags
defaultOption component listOption / OptionGroup
headerContent at the top of the dropdown list—
footerContent at the bottom of the dropdown list—
prefixContent as Select prefix—
emptyContent when there are no options—
tagContent of custom tags, only works when multiple is true—
loadingContent of custom loading—

Option Attributes ​

NameDescriptionTypeDefault
valueValue of optionstring / number / boolean / object—
labelLabel of option, same as value if omittedstring / number—
disabledWhether option is disabledbooleanfalse

OptionGroup Attributes ​

NameDescriptionTypeDefault
labelName of the groupstring—
disabledWhether to disable all options in this groupbooleanfalse

Best Practices ​

  1. Performance Optimization: Use virtual scrolling or pagination for large datasets
  2. User Experience: Provide appropriate placeholders and loading states
  3. Data Validation: Ensure data integrity and consistency of options
  4. Accessibility: Provide keyboard navigation and screen reader support
  5. Responsive Design: Maintain good display across different screen sizes
  6. Error Handling: Handle network errors and data loading failures gracefully

Summary ​

The Select component is a powerful form component that supports:

  • Single and multiple selection modes
  • Local and remote search
  • Option grouping and custom templates
  • Multiple sizes and states
  • Rich configuration options
  • Good accessibility support

Mastering the Select component will help you build more flexible and user-friendly form interfaces.

References ​

Element Plus Study Guide