Open
Description
Problem to solve
This can be used to provide users with a quick way to input data without cluttering the ui. You are able to tag notes using #Important
, make links clickable within text fields and highlight special search terms like assigned-to:me
in a search inputs.
Proposed solution
Example:
<template>
<v-text-field v-model="text" :slots="slots">
<template slot="days" slot-scope="{ match, removeMatch, deleteText }">
<!-- removeMatch keeps the text but doesn't render the slot in its place (it will match again if the matched text changes (eg appending a "s" to "day")) -->
<v-chip @click="removeMatch">
<v-icon left>mdi-calendar-clock</v-icon>
<!-- match is the return value of RegExp.exec() -->
{{match[0]}}
<!-- deleteText removes the matched text -->
<v-icon right @click.stop="deleteText">mdi-close</v-icon>
</v-chip>
</template>
</v-text-field>
</template>
<script>
export default {
data() {
return {
text: "",
slots: [
{
// this slot will replace matched text with the component provided via slots ...
match: /\bin\s+(\d+)\sdays?\b/,
// ... only if this method returns true
verify(match) {
return Number(match[1]) < 100;
},
// the name of the slot
name: "days",
// limits the number of matches; if the user were to input "in 1 day" twice, only the latter occurence will be matched
limit: 1,
},
],
};
},
};
</script>
The result should look like this example from todoist:
removeMatch should work like this :
There is an example with <a :href="match[0]">{{match[0]}}</a>
as template:
Another example with a list of available values:
For this to work, an additional method getItems
has to be provided. The list itself should be similar to v-combobox
.
<script>
export default {
data() {
return {
text: "",
projects: [
// value will be inserted upon click, text will be displayed in the list (if no list-item slot is provided)
{ text: "Inbox", value: "#Inbox" },
{ text: "School", value: "#School" },
{ text: "Demo Project", value: "#Demo Project" },
],
slots: [
{
match: /\b#([\w\s])+\b/i,
verify(match) {
// only render the chip if the project exists
return !!this.projects.find(
(project) => project.value === match[1],
);
},
// all items to display in the list, can be customized using the list-item slot
getItems() {
return new Promise((resolve) => {
setTimeout(() => {
resolve(this.projects);
}, 500);
});
},
name: "project",
// no limit
limit: 0,
},
],
};
},
};
</script>