2

I need to add class to label element when I focus on an input element which is below the label. My current solution is this:

HTML:

<label for="formProductId" ref="productIdLabel" class="form-element-title">Product ID</label>
<input id="formProductId" @blur="toggleFocus('productIdLabel', false)" @focus="toggleFocus('productIdLabel', true)" v-model="filterValues.productId" :name="filterOptions.productId === true ? 'productId' : false" type="text">

JS:

toggleFocus(ref: string, enable: boolean) {
    if (enable) {
        (this.$refs[ref] as HTMLElement).classList.add("js-focused");
    } else {
        (this.$refs[ref] as HTMLElement).classList.remove("js-focused");
    }
}

I would like to remove the ref attribute and toggle js-focused class completely by the selected element itself. How do I select the closest label element and edit it's class?

2 Answers 2

1

A better approach is to use dynamic class. See this example:

new Vue({
  el: '#app',
  data: {
    productIdLabel: false
  }
})
.js-focused {
  background-color: lightblue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id='app'>
  <label for="formProductId" class="form-element-title" :class="{'js-focused': productIdLabel == true}">Product ID</label>
  <input id="formProductId" @blur="productIdLabel = false" @focus="productIdLabel = true" type="text">
</div>

Use with component and multiple form inputs:

Vue.component("form-label", {
  template: `<div>
	  <label :for="info.id" class="form-element-title" :class="{'js-focused': isFocused == true}">{{info.label}}</label>
   <input :id="info.id" @blur="isFocused = false" @focus="isFocused = true" type="text">
	</div>`,
	props: ["info"],
	data: function(){
		return {
			isFocused: false
		}
	}
})
new Vue({
  el: '#app',
  data: {
    form: [{
      label: "Product Id",
      id: "formProductId"
    }, {
      label: "Another Element",
      id: "anoterId"
    }, {
      label: "Third Element",
      id: "thirdId"
    }]
  }
})
.js-focused {
  background-color: lightblue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id='app'>
  <form-label v-for='el in form' :info='el'></form-label>
</div>

Sign up to request clarification or add additional context in comments.

2 Comments

Isn't it a bad practice to have a variable for each label? I have a number of labels and inputs on my component so I would need a variable for each label.
Not necessarily. It might make your code unmaintainable. If you have number of form elements you can use a component and then iterate your form data over it. The component will have one variable for focus. I will update my answer.
1

You can use previousElementSibling with event.target.

Example:

new Vue({
  el: '#app',
  methods: {
    toggleLabelColor(event) {
      event.target.previousElementSibling.classList.toggle('input-focused')
    }
  }
})
input {
  display: block;
}

.input-focused {
  color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <label>I turn green when focused.</label>
  <input @focus="toggleLabelColor" @blur="toggleLabelColor">

  <label>I turn green when focused.</label>
  <input @focus="toggleLabelColor" @blur="toggleLabelColor">

  <label>I turn green when focused.</label>
  <input @focus="toggleLabelColor" @blur="toggleLabelColor">
</div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.