<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>Validation</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.0/font/bootstrap-icons.css"
/>
<style type="text/css">
.display-flex {
display: -webkit-flex;
display: flex;
}
.c-button-secondary {
background-color: #fff;
border: 1px solid #3f7cd8;
padding: 5px 16px;
color: #3f7cd8;
}
.c-button {
cursor: pointer;
position: relative;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
padding: 10px 16px;
gap: 4px;
border-radius: 100px;
font-weight: 700;
font-size: 1.4rem;
min-width: 80px;
word-break: keep-all;
}
.add-tag-container {
flex-wrap: wrap;
}
.add-tag-label {
display: flex;
align-items: center;
margin-right: 10px;
margin-bottom: 10px;
}
.add-tag-label-remove {
font-size: 24px;
color: #3f7cd8;
margin-left: 5px;
cursor: pointer;
}
.add-tag-label-remove:hover {
font-size: 24px;
color: #77a1e0;
margin-left: 5px;
cursor: pointer;
}
.inner {
height: 47px;
display: -webkit-box;
word-break: break-all;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.control-label {
text-align: left;
margin-right: 5px;
}
.tag-suggestions {
position: absolute;
top: 100%;
left: 0;
width: 90%;
max-height: 150px;
overflow-y: auto;
border: 1px solid #ccc;
background-color: #fff;
z-index: 1;
overflow-y: hidden;
max-height: 400px;
}
.tag-suggestions li,
.tag-message {
list-style: none;
padding: 8px;
cursor: pointer;
border-bottom: 1px solid #eee;
height: 40px;
}
.tag-suggestions li:last-child {
border-bottom: none;
}
.customize-error {
position: absolute;
top: 100%;
left: 0;
width: 90%;
max-height: 150px;
overflow-y: auto;
}
</style>
</head>
<body>
<div id="app">
<h1>Test</h1>
<div
class="form-group form-height display-flex"
style="margin-left: 10px; width: 768px"
>
<label class="col-xs-12 control-label inner col-sm-4">Tag</label>
<div class="input-group col-xs-12 col-sm-7 layout-input-2 display-flex">
<input
type="text"
class="form-control inputTagInfo"
placeholder="please input tag name"
v-model="tagInput"
name="tagInput"
v-on:focus="focusTag()"
v-on:blur="blurTag()"
data-vv-as="Tag"
data-vv-scope="tag-insert-scope"
v-validate="'required'"
autocomplete="off"
/>
<div style="padding-left: 10px; width: 10%">
<button type="button" class="btn btn-default" @click="addTags">
<i class="bi bi-plus-square"></i>
</button>
</div>
<ul class="tag-suggestions" v-show="showTagFlg">
<div class="" v-show="showTagLoading">
<div class="tag-message">loading</div>
</div>
<div v-show="!showTagLoading">
<div v-show="showTagList.length">
<li
v-for="(item, index) in showTagList"
:value="item.tagName"
:key="item.tagId"
@mousedown.prevent="chooseTag(item)"
>
{{ item.tagName }}
</li>
</div>
<div class="tag-message" v-show="!showTagList.length">
no data
</div>
</div>
</ul>
<span
v-show="errors.has('tagInput', 'tag-insert-scope')"
class="error customize-error"
>
{{ errors.first('tagInput', 'tag-insert-scope') }}</span
>
</div>
</div>
<div
class="form-group form-height display-flex"
style="margin: 25px 0 0 10px; width: 768px"
>
<div class="col-xs-12 control-label inner col-sm-4"></div>
<div class="display-flex add-tag-container">
<div v-bind:key="index" v-for="(item, index) in tagList">
<div class="add-tag-label">
<button type="button" class="c-button c-button-secondary">
#{{item.tagName}}
</button>
<div class="add-tag-label-remove">
<i class="bi bi-trash" @click="removeTag(index)"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.13"></script>
<script src="https://cdn.jsdelivr.net/npm/vee-validate@2.1.0-beta.9/dist/vee-validate.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vee-validate@2.1.0-beta.9/dist/locale/ja.js"></script>
<script>
Vue.use(VeeValidate);
new Vue({
el: "#app",
data: {
tagInput: "",
showTagFlg: false,
showTagLoading: false,
origintagList: [
{
tagId: 1,
tagName: "tag1",
},
{
tagId: 2,
tagName: "tag2",
},
{
tagId: 3,
tagName: "tag3",
},
{
tagId: 4,
tagName: "tag4",
},
{
tagId: 5,
tagName: "tag5",
},
],
showTagList: [],
tagList: [
{
tagId: 1,
tagName: "tag1",
},
{
tagId: 2,
tagName: "tag2",
},
{
tagId: 3,
tagName: "tag3",
},
],
},
created() {
// this.$validator.localize("ja");
this.$validator.localize("en");
},
methods: {
addTags: function () {
this.$validator.validate("tag-insert-scope.*").then((result) => {
if (!result) {
return;
}
const isTagDuplicate = this.checkTagDuplicate();
if (isTagDuplicate) {
return;
}
if (this.choosedTag && null != this.choosedTag.tagId) {
this.tagList.push(this.choosedTag);
this.choosedTag = {};
} else {
const newItem = {
tagName: this.tagInput,
};
this.tagList.push(newItem);
}
});
},
removeTag: function (index) {
this.tagList.splice(index, 1);
this.$validator.errors.clear("tag-insert-scope");
this.checkTagDuplicate();
},
checkTagDuplicate: function () {
const isTagDuplicate = this.tagList.some(
(item) => item.tagName === this.tagInput
);
if (isTagDuplicate) {
this.$validator.errors.add({
field: "tagInput",
msg: "There are duplicate names among the following tags, please choose again.",
scope: "tag-insert-scope",
});
this.choosedTag = {};
return true;
}
return false;
},
focusTag() {
if (document.activeElement.className.includes("inputTagInfo")) {
this._debounce(this.getSelectData(this.tagInput), 500);
}
this.showTagFlg = true;
},
_debounce(func, wait) {
let timeout;
return function () {
let _this = this;
let args = arguments;
clearTimeout(timeout);
timeout = setTimeout(function () {
func.apply(_this, args);
}, wait);
};
},
blurTag() {
this.showTagFlg = false;
},
getSelectData(tagInput) {
this.showTagList = this.origintagList.filter((item) => {
return item.tagName.match(tagInput);
});
},
chooseTag(choosedTag) {
this.isSelecting = true;
this.tagInput = choosedTag.tagName;
this.choosedTag = choosedTag;
this.blurTag();
this.$nextTick(() => {
this.isSelecting = false;
});
},
},
watch: {
tagInput: {
handler: function () {
if (!this.isSelecting) {
this.focusTag();
}
},
},
},
});
</script>
</body>
</html>
vue实现input的实时搜索(防抖版)
最新推荐文章于 2024-08-27 04:39:19 发布