0

I have two JS variables that contain the IDs of an HTML input element and a span element respectively.

const male1DOB = document.getElementById('male1-dob');
const male1DOBError = document.getElementById('male1-dob-error');

I want to reference these two elements in a function. Of course, one way to do it would be to pass the two element objects to the function like this:

validateElemId(maleDOB, maleDOBError);
...
function validateElemId(elem, elemError) {
    // Print value of input element
    console.log(elem.value);
    // Print error string
    console.log(elemError.innerHTML);

But since these elements share a common prefix, it would be cleaner and terser to just pass that prefix to the function as a string and then interpolate it in the function something like this:

validateElemId(maleDOB);
...
function validateElemId(elem) {
    console.log(<elem>.value);
    console.log(<elem>Error.innerHTML);
}

How do you do this? If I do this:

validateElemId('maleDOB')
...
function validateElemId(elem) {
    console.log(`${elem}.value`);

I get the following instead of the actual value of the element:

maleDOB.value

If I do this instead:

validateElemId(maleDOB):
...
function validateElemId(elem) {
    console.log(elem.value);
    console.log(elemError.innerHTML);

I get the correct element value but I get an error for elemError:

Uncaught ReferenceError: elemError is not defined.
Jim
  • 13,430
  • 26
  • 104
  • 155
  • 1
    Well your variables do not contain ids but HTML elements, that's the problem. Take alook at https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById. You need to call elementById inside the fuction with a string literal, that should solve the problem. – Berk Kurkcuoglu Jun 04 '20 at 21:40
  • 1
    "*But since these elements share a common prefix, it would be cleaner and terser to just pass that prefix to the function as a string and then interpolate it in the function*" this is *the exact opposite* of "clean". You're trying to tie how your function operates with the names of the variables *you are calling it with*. So, the implementation of the function is entirely reliant on the way you're invoking it, leading to *extremely* brittle and tightly coupled code. Also, *extremely* hard to reuse. – VLAZ Jun 04 '20 at 21:43
  • 1
    On top of it, you're transitively trying to use [variable variables](https://stackoverflow.com/questions/5187530/variable-variables-in-javascript) which is bad of itself but even worse since you're trying to do reach variables in a completely different scope through a call. The only reliable way to do that is to make them global which is even worse than usual. – VLAZ Jun 04 '20 at 21:45
  • @VLAZ OK. So what do you think is the correct way to handle this situation? Thanks! – Jim Jun 05 '20 at 03:40
  • 1
    The correct way is to do nothing at all. Your code is neither inefficient, nor unclear, nor anything. You're optimising for variable names which is pretty useless thing to optimise for. The function *should* be agnostic towards stylistic names such as variable names. Otherwise if a minifier changes your variables (normally a safe operation), your code might break. Receiving two parameters is also fine if you need to work with two things. It's more reusable that way. – VLAZ Jun 05 '20 at 14:12

4 Answers4

3

I think you can do something like this:

function validateElemId(text) {
  const male1DOB = document.getElementById(text);
  const male1DOBError = document.getElementById(`${text}-error`);

  console.log(male1DOB.value);
  console.log(male1DOBError.innerHTML);
}

By the way your question is not 100% clear, anyway I hope it helps you.

GirkovArpa
  • 4,427
  • 4
  • 14
  • 43
GM-atteoni
  • 425
  • 4
  • 11
1

I would suggest you simply wrap them in an object named male1DOB

const male1DOB = {
  'value': document.getElementById('male1-dob'),
  'error': document.getElementById('male1-dob-error')
}

Now you just pass this to the function

validateElemId(male1DOB);
...
function validateElemId(elem) {
    console.log(elem.value);
    console.log(elem.error.innerHTML);
}
Ahmed Hammad
  • 2,798
  • 4
  • 18
  • 35
0

In this part of your code

validateElemId('maleDOB')
...
function validateElemId(elem) {
    console.log(`${elem}.value`);

you are only passing the element 'maleDOB' but you are not retrieving it, and its the same case for elemError.innerHTML

if you want to deal with ids you can simply create a function like this

function retrieveElem(id){
     return  document.getElementById(id)}

and then you can use anywhere in your code it like this

const elem=retrieveElem('maleDOB') 
validateElemId(elem)
...
function validateElemId(elem) {
    console.log(`${elem}.value`);
Sven.hig
  • 4,449
  • 2
  • 8
  • 18
0
<input id="male1-dob" value="foo" />
<textarea id="male1-dob-error">bar</textarea>

<script>
  function validateElemId(elem) {
    elem = Object.keys(elem)[0];
    console.log(eval(`${elem}.value`));
    console.log(eval(`${elem}Error.innerHTML`));
  }

  const maleDOB = document.getElementById('male1-dob');
  const maleDOBError = document.getElementById('male1-dob-error');

  validateElemId({ maleDOB }); 
  // foo
  // bar
</script>
GirkovArpa
  • 4,427
  • 4
  • 14
  • 43