简体   繁体   中英

Only enable element once all input fields are filled. Reusable function

I am trying to write a reusable function which loops through all input fields, if any are empty I want another element (a href or button) to be toggle a class name (disabled).

Currently it works on the first input but not the second, I think this relates to the jquery selector.

JS:

const toggleElem = () => {
    const parent = $('.fileUploader--videos');
    const $input = parent.find('[type="text"]'); // I think this is the issue
    const $wrapper = parent.find('.fileUploader-wrapper');
    const visibleClass = 'visible';
    $input.on('change input', () => {
        toggleElemValidInput($input, $wrapper, visibleClass);
    });
};

toggleElem();

const toggleElemValidInput = (input, elem, className) => {
    input.each(function() {
        if ($(this).val() !== '') {
        // also would prefer if ($(this).val().length !== 0)
            elem.addClass(className);
        } else {
            elem.removeClass(className);
        }
    });
};

HTML:

<div class="fileUploader col fileUploader--videos hasAdvancedUpload" data-action="/api/v1/ProductMediaVideoUploadApi" data-method="post">
  <label for="videoTitle" class="mb-3">
    <input type="text" name="videoTitle" value="" class="form-control" placeholder="Add video title" autocomplete="off">
  </label>
  <label for="videoUrl" class="mb-3">
    <input type="text" name="videoUrl" value="" class="form-control" placeholder="Add video url" autocomplete="off">
  </label>
  <i class="fileUploader__icon fa fa-film"></i>
  <div class="fileUploader__input">
    <input class="fileUploader__file" type="file" name="file-videos" id="file-videos" accept="image/x-png,image/gif,image/jpeg">
    <label for="file-videos">Click to add a video thumbnail</label>
    <p class="fileUploader__dragndrop"> or drag it here</p>
    <ul class="small">
      <li>File formats: </li>
      <li>File size: <span class="file-size-max"></span></li>
    </ul>
  </div>
  <div class="fileUploader__uploading">Uploading...</div>
  <div class="fileUploader__success">Complete</div>
  <div class="fileUploader__error">Error. <span></span></div>
  <a href="#" class="fileUploader__restart fa fa-redo-alt"></a>
  <div class="fileUploader-wrapper mt-3 text-right">
    <a href="#" class="btn btn-primary btn-submit">Submit</a>
  </div>
</div>

I have made a fiddle here: https://jsfiddle.net/lharby/zygw72pr/

I kind of understand creating this function and only targeting one selector, but my goal is to make it reusable and it should not matter if there is 1 input or 100.

TIA

Filter all the textboxes. When there are no empty ones, set the class to visible.

var query = "input[type=\"text\"]";

$(query).on("input change", () =>
{
  if($(query).filter((a, b) => $(b).val().length == 0).length == 0)
       $(".fileUploader-wrapper").addClass("visible");
  else
       $(".fileUploader-wrapper").removeClass("visible");
});
  

The problem is the toggling of the class is dependent on only the last input in the collection the way you have written it in the loop like that.

You could use filter() to get collection of the ones that are empty (if any) and use that collection length to determine the class toggling.

Using toggleClass() with it's boolean second argument is also simpler than writing both addClass() and removeClass() in a conditional

Something like:

const toggleElemValidInput = (input, elem, className) => {
    const hasEmpty = !!input.filter((i,el) => !el.value.trim()).length;
    elem.toggleClass(className, hasEmpty);
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM