0

So I have the following jQuery code that I've built out that checks whether a on change event has been triggered on #rtk5 and then either removes or adds the 'required' attribute.

Works perfectly in jQuery:

// Make checkbox textboxes not required unless checked
$(document).ready(function() {
    $('#rtk5').change(function() {
        if ($('.rtk5ReqField').attr('required')) {
            $('.rtk5ReqField').removeAttr('required');
        }
        else {
            $('.rtk5ReqField').attr('required','required');
        }
    });
});

I would like to convert it to JavaScript with a function call, but I can't seem to figure out how to properly do it.

Error:
TypeError: rtk5req.getAttribute is not a function

Here is my attempt:

var rtk5req = document.getElementsByClassName('rtk5ReqField');
function rtk5Required() {
    rtk5req.addEventListener('change', (e) => {
        if (rtk5req.getAttribute('required')) {
            rtk5req.removeAttribute('required');
        } else {
            rtk5req.getAttribute('required', 'required');
        }
    });
}
rtk5req.addEventListener('change', rtk5Required());
document.addEventListener('DOMContentLoaded', rtk5Required);
rtk5Required();

Updated code: Removed the repetitive change call

var rtk5req = document.getElementsByClassName('rtk5ReqField');
function rtk5Required() {
        if (rtk5req.getAttribute('required')) {
            rtk5req.removeAttribute('required');
        } else {
            rtk5req.getAttribute('required', 'required');
        }
}
rtk5req.addEventListener('change', rtk5Required());
document.addEventListener('DOMContentLoaded', rtk5Required);
rtk5Required();

Updated code #2:

Thanks all for all the hard work, there's one small issue that I'm still experiencing and had to make some tweaking - When I uncheck the checkbox, it doesn't remove the required tag placed on rtk5Declaration from which it did in the jQuery.

var rtk5_selection = document.getElementById('rtk5');

document.addEventListener('DOMContentLoaded', () => {
    rtk5_selection.addEventListener('change', () => {
        if (rtk5_selection.getAttribute('required')) {
            document.getElementById('rtk5Declaration').removeAttribute('required');
        } else {
            document.getElementById('rtk5Declaration').setAttribute('required', 'required');
        }
    });
});

Thanks so much all!

  • 2
    `.getElementsByClassName` returns an `HTMLCollection` of elements, not a single element. You need to iterate over it. – Alnitak Jan 09 '20 at 15:39
  • So I've removed the `rtk5req.addEventListener('change', (e) => {` portion because it seemed redundant with the `rtk5req.addEventListener('change', rtk5Required());`. –  Jan 09 '20 at 15:41
  • 1
    it won't work until you address the fact that `rtk5req` is a pseudo-array, not a single element. – Alnitak Jan 09 '20 at 15:43
  • here `rtk5req.addEventListener('change', rtk5Required());` you should pass the reference of the `rtk5Required` function without calling it. – hawks Jan 09 '20 at 15:45
  • 1
    how many elements are known to exist with this particular class? It affects how any answer might be written. – Alnitak Jan 09 '20 at 15:45
  • @Alnitak, there is only one. –  Jan 09 '20 at 15:46
  • 1
    Right, in which case I see the problem - you should just change the second code to use `var rtk5req = document.getElementById('rtk');` instead of using its class and the more complicated `getElementsByClassName()` function. – Alnitak Jan 09 '20 at 15:47
  • 1
    and don't use the updated code - as pointed out by @ajuni880 it's flawed. – Alnitak Jan 09 '20 at 15:48
  • Let me attempt some changes and I will respond back as soon as possible - Thanks for all the help. –  Jan 09 '20 at 15:49
  • 1
    @SLE correct me if I'm wrong, but shouldn't you be using `prop('required')` for getting the property and `prop('required', true)` or `prop('required', false)` for setting the property? – Mihail Minkov Jan 09 '20 at 16:22
  • When you say convert it to JavaScript, what you actually mean is remove JQuery which is JavaScript and use the standard DOM routines. Why? JQuery offers so much more portability and it is JavaScript, just need to make sure you have the required files for your use. – SPlatten Jan 09 '20 at 16:25
  • @MihailMinkov That's correct. I believe either can be used but this is specifically what `.prop()` is meant to be used for. **Reference:** [stackoverflow.com/questions/19166685/jquery-add-required-to-input-fields](https://stackoverflow.com/questions/19166685/jquery-add-required-to-input-fields#answer-19166712) – War10ck Jan 09 '20 at 16:37

2 Answers2

1

Since you only have one element you should be using its ID instead of its class, and avoiding the complication caused by document.getElementsByClassName returning a pseudo-array of elements instead of a single element.

NB: use setAttribute to change an attribute's value, or better yet (as shown in the code below) use the direct boolean property that mirrors the element's attribute.

document.addEventListener('DOMContentLoaded', () => {

    const rtk_sel = document.getElementById('rtk5');
    const rtk_dec = document.getElementById('rtk5Declaration');

    rtk_sel.addEventListener('change', () => {
        rtk_dec.required = !rtk_sel.checked;
    });
});
Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • Thanks for the guidance @Alnitak, however I think I might need to do some tweaking because it's checking if the ID `#rtk5` has a on change event triggered and then instead of using the `.rtk5ReqField` class, I will be using the ID `rtk5Declaration` to apply the required attribute there. –  Jan 09 '20 at 16:01
  • Assuming based on your comments that there's a single `.rtkReqField` element and that it's the one with the `#rtk` ID, the code here should exactly replicate your existing jQuery code. If you need to tweak it that's a different problem. – Alnitak Jan 09 '20 at 16:07
  • Thanks a bunch @Alnitak, I updated a answer with one small issue that I'm experiencing. –  Jan 09 '20 at 16:17
0

Thanks all for the contribution, below is the working version which I have tweaked:

var rtk5_selection = document.getElementById('rtk5');
var rtk5declaration = document.getElementById('rtk5Declaration');

function rtd3Declaration() {
    if (!rtk5_selection.checked) {
        rtd3declaration.removeAttribute('required');
    } else {
        rtd3declaration.setAttribute('required', 'required');
    }
}
rtk5_selection.addEventListener('change', rtd3Declaration);
document.addEventListener('DOMContentLoaded', rtd3Declaration);
rtd3Declaration();
  • ah, so it's two different elements? You didn't mention that in the question. Personally I'd still use `rtd3declaration.required` as a property (as you've done with rtk5_selection.checked` rather than mess about with calls to `removeAttribute`. In fact you could just do: `rtd3declaration.required = !rtk5_selection.checked`. (see my updated answer) – Alnitak Jan 09 '20 at 17:45
  • Thanks for the guidance @Alnitak, I'll still accept it as the final answer since it helped pave the way. –  Jan 09 '20 at 17:48
  • NB: you shouldn't call `rtd3Declaration` separately, and you should move the `getElementById` calls _inside_ that function, to ensure that they actually succeed. If they're called before the DOM is loaded they won't hold the right values. – Alnitak Jan 09 '20 at 17:48