Search code examples
javascriptstimulusjs

In Javascript, how can I check that DOM elements input has changed without hardcoding and comparing values?


I have the following StimulusJS controller that aims to track certain required elements (flatckpickr date selectors).

Once all those date pickers' dates have been selected, I have to enable the submit button in a form.

I'm having problems tracking that all the required inputs have been inputed by the user and since this should be a reutilizable controller, I can't hardcode a value and compare against it.

What would be an effective way to check that all requiredTargets have received input from the user?

import { Controller } from 'stimulus';

export default class extends Controller {
  static targets = ["required", "deactivable"];

  toggle(){
    this.deactivableTargets.toggleAttribute("disabled");
  }

  connect() {
    
    this.requiredTargets.forEach((element) => {

      element.addEventListener('input', (event) => {

        console.log(`${element} changed`);

        //if (this.requiredTargets.inputed?) {
          toggle();
        }
      })
    })
  }
}

Solution

  • Technically inputs fields will have a value of an empty string ("") by default

    You can use the JavaScript Array.every method to check that all required fields have been filled and are not equal to an empty string.

    This will return true or false, and depending on what the case is, you can call the toggle() method

    My Approach

    On each flatpickr HTML input element, connect a Stimulus action method that fires on input event.

    Let's call it handleInput in this case, so our HTML should look like this

    <input
      data-<controller-name>-target="required"
      data-action="<controller-name>#handleInput"
      type="text"
      placeholder="Select Date.."
      data-input
    >
    <!-- replace <controller-name> with the actual stimulus controller name -->
    

    Next, define the handleInput method in your controller like this

    handleInput() {
      const isRequiredFilled = this.requiredTargets.every(el => el.value !== '');
    
      if (isRequiredFilled) {
        this.toggle();
      }
    }
    

    NB: input element has a default input event so you don't have to handle that yourself. See the documentation