Home > Back-end >  Adding a class to Vue child component from a parent component
Adding a class to Vue child component from a parent component

Time:01-19

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>
  •  Tags:  
  • Related