Vue 2 - 禁用输入 - 多个组件
大家好,
我很难解决一个问题,一旦第一个字符输入到另一个输入字段中,我想要禁用其他输入字段。
我一直试图用$ emit,@ focus和其他解决方案解决这个问题,但我仍然陷入困境。我也无法利用这里的答案。
段:
const Autocomplete = {
name: "autocomplete",
props: {
items: {
type: Array,
required: false,
default: () => ['test']
},
isAsync: {
type: Boolean,
required: false,
default: false
},
formLock: {
type: Boolean,
},
formId: {
type: String,
}
},
data() {
return {
isOpen: false,
results: [],
search: "",
isLoading: false,
arrowCounter: 0,
};
},
methods: {
onChange() {
// Let's warn the parent that a change was made
this.$emit("input", this.search);
// Is the data given by an outside ajax request?
if (this.isAsync) {
this.isLoading = true;
} else {
// Let's search our flat array
this.filterResults();
this.isOpen = true;
}
if (this.search.length === 0) {
this.isOpen = false;
}
console.log(this.search.length);
},
disableOther() {
var searchForms = document.getElementsByClassName('searchForm');
for (i = 0; i < searchForms.length; i++) {
}
console.log(searchForms.length);
},
filterResults() {
// first uncapitalize all the things
this.results = this.items.filter(item => {
return item.toLowerCase().indexOf(this.search.toLowerCase()) > -1;
});
},
setResult(result) {
this.search = result;
this.isOpen = false;
},
onArrowDown(evt) {
if (this.arrowCounter < this.results.length) {
this.arrowCounter = this.arrowCounter + 1;
}
},
onArrowUp() {
if (this.arrowCounter > 0) {
this.arrowCounter = this.arrowCounter - 1;
}
},
onEnter() {
this.search = this.results[this.arrowCounter];
this.isOpen = false;
this.arrowCounter = -1;
},
handleClickOutside(evt) {
if (!this.$el.contains(evt.target)) {
this.isOpen = false;
this.arrowCounter = -1;
}
}
},
mounted() {
document.addEventListener("click", this.handleClickOutside);
},
destroyed() {
document.removeEventListener("click", this.handleClickOutside);
},
template: `
<div>
<input type="text" @input="onChange" class="searchForm" v-model="search" @keyup.down="onArrowDown" @keyup.up="onArrowUp" @keyup.enter="onEnter" v-bind:disabled="formLock" @focus="disableOther" />
<ul id="autocomplete-results" v-show="isOpen" class="autocomplete-results">
<li class="loading" v-if="isLoading">
Loading results...
</li>
<li v-else v-for="(result, i) in results" :key="i" @click="setResult(result)" class="autocomplete-result" :class="{ 'is-active': i === arrowCounter }">
{{ result }}
</li>
</ul>
</div>
`,
};
new Vue({
el: "#productSearchApp",
name: "productSearchApp",
data() {
return {
productName: [],
productCatalog: [],
lock: false,
searchName: "searchForm",
searchCatalog: "searchCatalog"
}
},
mounted() {
fetch("http://cormay.314-work.pl/wp-json/wp/v2/product")
.then(response => response.json())
.then((data) => {
for (i = 0; i < data.length; i++) {
this.productName.push(data[i].title.rendered);
};
for (i = 0; i < data.length; i++) {
this.productCatalog.push(data[i].product_catalog);
};
})
},
components: {
autocomplete: Autocomplete,
},
methods: {
updateLock(updateLock) {
this.lock = updateLock;
}
}
});
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="productSearchApp">
<autocomplete :items="productName" :form-id="searchName"></autocomplete>
<autocomplete :items="productCatalog" :form-id="searchCatalog"></autocomplete>
</div>
谢谢!
答案 0 :(得分:0)
也许您可以使用像VueX或Instance Properties这样的州经理 ......喜欢:
// global state
Vue.prototype.$state = new Vue({
data: {
active: null
}
})
// input component
Vue.component('vue-input', {
props: ['value'],
template: `
<label>
<slot></slot>
<input v-model="model" :disabled="disabled" />
</label>
`,
data() {
return {
// avoid mutation
model: this.value
}
},
beforeDestroy() {
// reset state in case we remove the active component
if (this.$state.active === this) this.$state.active = null;
},
watch: {
model(value) {
// set active to 'this' if value length > 0 or null active value
this.$state.active = value.length ? this : null;
}
},
computed: {
disabled() {
// disable if active is not null and not equal to 'this'
return this.$state.active && this.$state.active !== this;
}
}
})
// app instance
new Vue({
el: '#app',
data: {
foo: null,
bar: null
}
})
label {
font: caption;
display: flex;
justify-content: space-between;
width: 160px;
margin-bottom: 10px;
}
input:disabled {
background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.js"></script>
<div id="app">
<vue-input v-model="foo">Foo</vue-input>
<vue-input v-model="bar">Bar</vue-input>
</div>
答案 1 :(得分:0)
你可以尝试这样的事情。
你会注意到我正在传递模型的名称,这可能看起来像是一个麻烦的管理,但如果你要将它配置为v-for循环的一部分,它会使它很容易管理。
Vue.component('custom-input', {
props: ['value', 'disabled'],
template: `
<input
:disabled="disabled"
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
`
})
new Vue({
el:'#app',
data:{
first: null,
second: null,
active: null
},
methods: {
onChange(e, model){
this.active = null
if (e.length > 0) {
this.active = model
}
}
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.js"></script>
<div id="app">
<custom-input v-model="first" :disabled="active !== null && active !== 'first'" @input="onChange($event, 'first')">Foo</custom-input>
<custom-input v-model="second" :disabled="active !== null && active !== 'second'" @input="onChange($event, 'second')">Bar</custom-input>
</div>