Vue-At: @-Mentions for Vue.js
vue-at is a JavaScript library that provides robust '@'-mentioning functionality, similar to At.js, but specifically engineered for Vue applications without relying on jQuery or injecting additional DOM nodes. It offers a lightweight and stable alternative for implementing user mentions in input fields. The library supports various Vue versions, including dedicated branches for Vue 1 (`vue-at@1.x` or `vue1-at`), Vue 2 (`vue-at@2.x`), and the current development focus, Vue 3 (`vue-at@next`, which is currently `3.0.0-alpha.3`). It is actively maintained with ongoing development for the latest Vue ecosystem. Key differentiating features include its plain-text based core, native support for both `contenteditable` divs and `textarea` elements, and extensive customization options for member lists and display templates. It also boasts compatibility with popular UI frameworks such as Vuetify and Element UI.
Common errors
-
Cannot find module 'textarea-caret' or its corresponding type declarations.
cause The `textarea-caret` package is a required peer dependency for the `AtTa` component, but it has not been installed.fixInstall the missing dependency: `npm install -S textarea-caret` or `yarn add textarea-caret`. -
[Vue warn]: Failed to resolve component: At If this is a native custom element, make sure to add it to 'compilerOptions.isCustomElement' in your setup.
cause This typically occurs in a Vue 3 project when `vue-at@2.x` (the Vue 2 compatible version) has been installed instead of `vue-at@next`, or when `vue-at` components are used in a Vue 3 context without proper component resolution setup.fixFor Vue 3 projects, ensure you install `vue-at@next`. If the issue persists, verify that Vue 3's component registration is correctly configured, and check if any build tools (like Vite) require specific configurations for external components. -
[Vue warn]: Property "members" was accessed during render but is not defined on instance.
cause The `members` prop, which defines the list of items for `@`-mentions, was not provided or correctly bound to the `At` or `AtTa` component.fixEnsure the `members` prop is explicitly passed to the `<at>` or `<at-ta>` component and that the `members` data property is defined in your component's script. Example: `<at :members="myMembersArray">` and `data() { return { myMembersArray: [...] } }`. -
TypeError: Cannot read properties of undefined (reading 'selectionStart') in textarea-caret.js
cause This error occurs within the `textarea-caret` library, likely indicating that it's trying to access properties of a textarea element that is not yet rendered or properly referenced, or `AtTa` is used incorrectly.fixEnsure the `<textarea>` element is correctly nested within `<at-ta>` and fully rendered before `vue-at` attempts to initialize the caret positioning logic. Also, verify `v-model` is correctly bound to the `<textarea>` itself.
Warnings
- breaking Vue 3 compatibility requires installing `vue-at@next`. The default `npm install vue-at` will fetch the Vue 2.x compatible version, which is not designed for Vue 3 and will lead to runtime errors due to significant API changes in Vue 3 (e.g., global API, reactivity, lifecycle hooks, v-model behavior).
- gotcha When using the `<AtTa>` component for textarea elements, the `textarea-caret` package is a mandatory dependency that must be installed separately. Failing to install it will likely result in errors related to missing modules or incorrect caret positioning for mention suggestions.
- gotcha The `vue-at@next` version for Vue 3 is currently in an alpha state (`3.0.0-alpha.3`). While functional, alpha releases may contain bugs, lack full feature parity with stable versions, or introduce further breaking changes before a stable major release.
- deprecated The custom template slot syntax for Vue 1.x (`slot="item"` with `data-src` and `data-text` attributes) is an outdated pattern. Modern Vue (2.x and 3.x) uses scoped slots or `v-slot` directives for passing data to child components' slots, making the Vue 1.x approach non-idiomatic and potentially incompatible.
- gotcha When using `v-model` with `<at>` (for `contenteditable` elements) versus `<at-ta>` (for `<textarea>` elements), the `v-model` should be bound to the `<at>` container itself for `contenteditable`, but directly to the `<textarea>` element inside `<at-ta>`. Incorrect placement can lead to reactivity issues or failed updates.
Install
-
npm install vue-at -
yarn add vue-at -
pnpm add vue-at
Imports
- At
import { At } from 'vue-at' // No named export for default component const At = require('vue-at') // Not standard for Vue 3 ESM projectsimport At from 'vue-at'
- AtTa
import AtTa from 'vue-at' // Incorrect path, AtTa is a subpath export
import AtTa from 'vue-at/dist/vue-at-textarea'
- Vue 3 Installation
npm install vue-at // Defaults to latest stable Vue 2.x version npm install vue-at@3.x // Specific 3.x tag not used, use @next
npm install vue-at@next
Quickstart
<template>
<at :members="members" v-model="message">
<div contenteditable style="border: 1px solid #ccc; padding: 8px; min-height: 50px;"></div>
</at>
<p>Current message: {{ message }}</p>
<at-ta :members="members" v-model="textareaMessage" style="margin-top: 20px;">
<textarea style="width: 100%; height: 80px; padding: 8px; border: 1px solid #ccc;"></textarea>
</at-ta>
<p>Current textarea message: {{ textareaMessage }}</p>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import At from 'vue-at';
import AtTa from 'vue-at/dist/vue-at-textarea';
// Ensure 'textarea-caret' is installed: npm i -S textarea-caret
const message = ref('');
const textareaMessage = ref('');
const members = ref([
'Alice',
'Bob',
'Charlie',
'David',
{ name: 'Eve', display: 'Eve (Admin)' },
'Frank',
'Grace'
]);
</script>
<style>
.atwho-view {
position: absolute;
top: 0;
left: 0;
z-index: 99999999;
display: none;
background: white;
border: 1px solid #eee;
font-size: 14px;
list-style: none;
padding: 0;
margin: 0;
border-radius: 3px;
box-shadow: 0 5px 10px rgba(0,0,0,.1);
min-width: 120px;
}
.atwho-view ul {
list-style: none;
padding: 0;
margin: 0;
}
.atwho-view li {
display: block;
padding: 5px 10px;
cursor: pointer;
}
.atwho-view strong {
color: #66CCFF;
}
.atwho-view li.cur {
background: #66CCFF;
color: white;
}
</style>