I have a Vue component that has few child components (inputs of the same type). The number of inputs may vary and it depends on the user, But there is a requirement to have at least one input filled. So, for example, I may have 5 inputs, 4 of them can be empty and it still considered valid.
My problem is that I want to add a red border around the first input in the list when all the inputs are empty. I check the inputs on the parent component.
I have something like this in the parent component:
<template>
<custom-input v-for="(input, key) in inputs_num" :key=key" />
</template>
<script>
data() {
return {
inputValues: [],
inputs_num: 1
}
}
methods: {
checkInputs() {
const validInputsCounter = 0;
this.inputValues.forEach((input) => {
if(input.trim().length > 4) validInputsCounter ;
});
if(validInputsCounter == 0) {
// Add border to the first input in the list.
}
}
...
...
}
</script>
I couldn't figure out how should I set the border for the first input only.
CodePudding user response:
I'd recommend passing the highlight state as a prop on the child component.
<template>
<custom-input v-for="(input, key) in inputs_num" :key=key" :highlight="higlightInput(key)"/>
</template>
<script>
data() {
return {
inputValues: [],
inputs_num: 1
}
}
methods: {
highlightInput(key){
if(key == 0){
if(this.inputValues.find(i => i.trim().length > 4) != undefined){
return true;
}
}
return false;
}
}
</script>
Then in your child component you declare a "highlight" prop with a default of "false". Presumably have an <input> element in that template - you can apply the class like this:
<input type = "text" : ... />
Code not checked for validity. Syntax error hunting is left as an exercise for the reader.
CodePudding user response:
Maybe something like following snippet :
Vue.component('customInput', {
template: `
<div>
<input v-model="content.val" : @input="setData" />
</div>
`,
props: ['cont', 'cls'],
data() {
return {
content: this.cont,
}
},
methods: {
setData() {
this.$emit('update', this.content);
},
},
})
new Vue({
el: "#demo",
data() {
return {
inputValues: [{id: 0, val: ''}],
red: null
}
},
methods: {
addInput() {
const newId = this.inputValues.length
this.inputValues.push({id: newId, val: ''})
},
getData(e){
const newData = this.inputValues.map(obj => {
if (obj.id === e.id)
return { ...obj }
return obj
});
},
checkInputs() {
this.red = null
const invalid = this.inputValues.sort((a, b) => a.id - b.id).filter(e => e.val.trim().length < 4)
if (invalid.length === this.inputValues.length) this.red = invalid[0].id
}
}
})
.red {
border: 2px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<button @click="addInput">Add Input</button>
<custom-input v-for="(input, key) in inputValues" :key="key"
@update="getData"
:cont="input"
:cls="input.id === red ? 'red' : ''" ></custom-input>
<button @click="checkInputs">Check Inputs</button>
</div>
CodePudding user response:
You can try something like this:
<template>
<custom-input v-for="key in inputValues.length" :key="key" v-model.trim="itemValues[key - 1]" : />
</template>
<script>
export default
{
data() {
return {
inputValues: [],
}
},
computed:
{
allEmpty()
{
return !this.inputValues.some(item => (item || '').trim().length > 4);
}
}
}
</script>
