10

I'm developing an app that has different license types, and according to the license we need to disable/enable inputs.

One way is to put a conditional :disabled for each input but that's a lot of work and error prone, since we might forget to put it on some inputs.

I thought of using a directive like v-disable-all that searches for all inputs under the container and adds disabled to them.

I was wandering if there is a better solution or if there is already a solution like this?

Tomer
  • 17,787
  • 15
  • 78
  • 137

4 Answers4

12

I ended up creating this directive:

import Vue from "vue";

Vue.directive("disable-all", {
  // When all the children of the parent component have been updated
  componentUpdated: function(el, binding) {
    if (!binding.value) return;
    const tags = ["input", "button", "textarea", "select"];
    tags.forEach(tagName => {
      const nodes = el.getElementsByTagName(tagName);
      for (let i = 0; i < nodes.length; i++) {
        nodes[i].disabled = true;
        nodes[i].tabIndex = -1;
      }
    });
  }
});
Tomer
  • 17,787
  • 15
  • 78
  • 137
  • 1
    So pretty much what I said to do? Not sure why you didn’t just tick, but happy you got it sorted. –  Apr 30 '19 at 07:23
  • 5
    "I thought of using a directive like v-disable-all that searches for all inputs under the container and adds disabled to them." this is a quote from my question, and then i asked if there is another , better, way. you just told me to do what i wanted to do in the first place. Also you wrote it in simple JS and not as a Vue directive, so i gave you a thumbs up for the effort but you didn't really answer my question. – Tomer May 01 '19 at 08:12
10

I'am coming a bit late, but there is an attribute on the HTML element called "disabled", which ... disable every input in the tree.

<fieldset :disabled="!canEdit">
  ...
</fieldset>

canEdit could be a computed property or anything you want.

Elmatou
  • 1,324
  • 12
  • 18
5

You can do something like this:

let elems = document.getElementById('parentDiv').getElementsByTagName('input');

This will give you all the inputs inside a parent, then you can run a simple for loop to loop over them and set each one to disabled.

Something like this:

for(let i = 0; i < elems.length; i++) {
    elems[i].disabled = true;
}

Hope this helps set you on the right path.

let elems = document.getElementById('someid').getElementsByTagName('input');

console.log(elems);

for(let i = 0; i < elems.length; i++) {
  elems[i].disabled = true;
}
<html>
  <body>
    <div id="someid">
      <input type="text">
      <input type="text">
      <input type="text">
      <input type="text">
      <input type="text">
    </div>
  </body>
</html>
  • He could write a directive and append it to each input or the parent that does exactly as shown above. "One way is to put a conditional :disabled for each input but that's a lot of work and error prone, since we might forget to put it on some inputs." This covers all inputs inside a parent. –  Apr 29 '19 at 14:20
  • As I mentioned in the question, I'm aware of this solution, I was looking for a way to avoid it – Tomer Apr 29 '19 at 14:32
  • You could write a watch function that has an array of licenses and the inputs that should be available when a license is selected and on change. But again, you would have to add each input to the array. I can't think of anything else off the top of my head. –  Apr 29 '19 at 14:35
  • Won't this stop working if anything on the model changes because Vue will regenerate the UI? – xr280xr Nov 15 '19 at 21:06
  • "input" selector doesn't account for SELECT tags – R-D Jul 31 '20 at 14:49
1

Now you just need to wrap your fields inside <v-form :disabled="variable"></v-form>

pabloRN
  • 866
  • 10
  • 19