Mention
Rich mention input for quickly @-mentioning members or topics in long text.
Markup Schema Example
<script lang="ts" setup>
import { createForm } from '@silver-formily/core'
import { FormItem, Mention, Submit } from '@silver-formily/element-plus'
import { createSchemaField, FormProvider } from '@silver-formily/vue'
const form = createForm()
const { SchemaField, SchemaStringField } = createSchemaField({
components: {
FormItem,
Mention,
},
})
const teammateOptions = [
{ value: 'Jasmine', label: 'Jasmine · Product Lead' },
{ value: 'Leo', label: 'Leo · Interaction Designer' },
{ value: 'Mia', label: 'Mia · Frontend Engineer' },
{ value: 'Oscar', label: 'Oscar · QA Engineer' },
]
const topicOptions = [
{ value: 'UX Improvements', label: '#ux-improvements' },
{ value: 'Weekly Release', label: '#weekly-release' },
{ value: 'Performance Tuning', label: '#performance-tuning' },
{ value: 'Risk Alert', label: '#risk-alert' },
]
async function log(value: any) {
console.log(value)
}
</script>
<template>
<FormProvider :form="form">
<SchemaField>
<SchemaStringField
name="status"
title="Team Updates"
x-decorator="FormItem"
x-component="Mention"
default="Aligned on the interaction draft with @Jasmine today and preparing to sync with @Mia for integration."
:x-component-props="{
rows: 3,
placeholder: 'Type @ to mention teammates',
options: teammateOptions,
}"
/>
<SchemaStringField
name="timeline"
title="Update with Topics"
x-decorator="FormItem"
x-component="Mention"
:x-component-props="{
rows: 3,
prefix: ['@', '#'],
split: ' ',
placeholder: 'Supports both @ teammates and # topics',
options: [...teammateOptions, ...topicOptions],
}"
/>
</SchemaField>
<Submit style="margin-top: 12px" @submit="log">
Submit
</Submit>
</FormProvider>
</template>Team Updates:
Update with Topics:
查看源码
Advanced Markup Schema Example
<script lang="ts" setup>
import { createForm } from '@silver-formily/core'
import { FormItem, Mention, Submit } from '@silver-formily/element-plus'
import { createSchemaField, FormProvider } from '@silver-formily/vue'
import { ref } from 'vue'
const form = createForm()
const { SchemaField, SchemaStringField } = createSchemaField({
components: {
FormItem,
Mention,
},
})
const reviewerPool = [
{ value: 'Elena', label: 'Elena · Design Reviewer' },
{ value: 'Kingsley', label: 'Kingsley · Engineering Reviewer' },
{ value: 'Doris', label: 'Doris · QA' },
{ value: 'Nico', label: 'Nico · Product' },
]
const reviewerOptions = ref([...reviewerPool])
const mentionLoading = ref(false)
const aliasOptions = [
{ id: 'u1001', nickname: 'Alex (Backend)', inactive: false },
{ id: 'u1002', nickname: 'Becca (Client)', inactive: true },
{ id: 'u1003', nickname: 'Chloe (Visual Design)', inactive: false },
]
function handleSearch(pattern: string) {
mentionLoading.value = true
const keyword = pattern.trim().toLowerCase()
setTimeout(() => {
reviewerOptions.value = keyword ? reviewerPool.filter(option => option.value.toLowerCase().includes(keyword)) : [...reviewerPool]
mentionLoading.value = false
}, 400)
}
function checkReviewer(pattern: string) {
return reviewerPool.some(option => option.value === pattern)
}
async function log(value: any) {
console.log(value)
}
</script>
<template>
<FormProvider :form="form">
<SchemaField>
<SchemaStringField
name="review"
title="Review Notes"
x-decorator="FormItem"
x-component="Mention"
default="@Elena, please review the interaction motion. @Kingsley, please keep an eye on performance regressions."
:x-component-props="{
rows: 3,
placeholder: 'Type @ to choose reviewers, with whole-token deletion via Backspace',
options: reviewerOptions,
loading: mentionLoading,
whole: true,
checkIsWhole: checkReviewer,
onSearch: handleSearch,
}"
/>
<SchemaStringField
name="alias"
title="Alias Configuration"
x-decorator="FormItem"
x-component="Mention"
:x-component-props="{
rows: 2,
placeholder: 'Map arbitrary fields through props and customize disabled rules',
options: aliasOptions,
props: { value: 'id', label: 'nickname', disabled: 'inactive' },
showArrow: true,
}"
/>
</SchemaField>
<Submit style="margin-top: 12px" @submit="log">
Save
</Submit>
</FormProvider>
</template>Review Notes:
Alias Configuration:
查看源码
Template Slot Example
<script lang="ts" setup>
import { createForm } from '@silver-formily/core'
import { FormItem, Mention, Submit } from '@silver-formily/element-plus'
import { Field, FormProvider } from '@silver-formily/vue'
const form = createForm()
const mentionOptions = [
{ value: 'UI Guide', label: 'UI Guide Update', owner: 'Jasmine' },
{ value: 'Performance Research', label: 'Performance Research', owner: 'Kingsley', disabled: true },
{ value: 'Release Checklist', label: 'Release Checklist', owner: 'Mia' },
]
async function log(value: any) {
console.log(value)
}
</script>
<template>
<FormProvider :form="form">
<Field
name="post"
title="Update Content"
:decorator="[FormItem]"
:component="[Mention, { rows: 3, placeholder: 'Type @ mentions here and customize the dropdown content', options: mentionOptions }]"
initial-value="@UI Guide now includes the visual specifications. @Release Checklist, please complete the QA entry."
>
<template #prefix>
<span class="mention-prefix">Update</span>
</template>
<template #suffix>
<span class="mention-suffix">⌘ + Enter to Publish</span>
</template>
<template #header="{ field }">
<div class="mention-panel-header">
Current field: {{ field?.title }}
</div>
</template>
<template #label="{ item, index, field }">
<div class="mention-option">
<span class="mention-option__index">{{ index + 1 }}</span>
<div class="mention-option__body">
<strong>{{ item.label }}</strong>
<small>Owner: {{ item.owner }}</small>
<small v-if="field?.value">Source field value: {{ field?.value.length }}</small>
</div>
</div>
</template>
<template #footer>
<div class="mention-panel-footer">
You can access the field through slots and render rich text content.
</div>
</template>
</Field>
<Submit style="margin-top: 12px" @submit="log">
Save
</Submit>
</FormProvider>
</template>
<style scoped>
.mention-prefix {
display: inline-flex;
align-items: center;
padding: 0 8px;
font-size: 12px;
color: var(--vp-c-text-2);
}
.mention-suffix {
font-size: 12px;
color: var(--vp-c-text-3);
}
.mention-panel-header,
.mention-panel-footer {
font-size: 12px;
padding: 4px 8px;
color: var(--vp-c-text-2);
}
.mention-option {
display: flex;
gap: 8px;
align-items: center;
}
.mention-option__index {
width: 20px;
height: 20px;
border-radius: 999px;
background-color: var(--vp-c-bg-soft);
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 12px;
}
.mention-option__body {
display: flex;
flex-direction: column;
font-size: 12px;
color: var(--vp-c-text-2);
}
.mention-option__body strong {
color: var(--vp-c-text-1);
}
.mention-option__body small {
font-size: 11px;
}
</style>Update Content:
Update⌘ + Enter to Publish
查看源码
API
See https://element-plus.org/en-US/component/mention.html
- The component fully forwards Element Plus Mention props and events. You can manage dropdown data through
dataSourceoroptions, and combinewhole,checkIsWhole,prefix, and similar capabilities to control mention behavior. - The
propsprop maps custom field names, so when a remote API returns keys such asidornickname, you do not need to transform them manually. onSearch(pattern, prefix, field)is called after a trigger character is typed. The third argument injects the current Formilyfield, which is useful for toggling loading state and updatingoptionsduring remote search.
Slots
| Slot | Description | Type |
|---|---|---|
prefix | Content before the input | -- |
suffix | Content after the input | -- |
prepend | Prepended content, shown before prefix | -- |
append | Appended content, shown after suffix | -- |
header | Dropdown header slot, with injected field | object |
footer | Dropdown footer slot, with injected field | object |
label | Custom option renderer with injected field, in addition to item and index | object |
loading | Custom loading content | -- |