0

I try to get some elements from html, that may or may not exist. Now if I just try

//previous code
document.getElementById("MyElement1").checked = false;
document.getElementById("MyElement2").checked = false;
...
//rest of the code

then the rest of the code won't get executed if one of the elements doesn't exist.

I would just do

try {
   document.getElementById("MyElement1").checked = false;
   document.getElementById("MyElement2").checked = false;
   ...
} catch (e) {
   console.log(e);
}

but it is said that you should never use a try...catch for non serious errors.

Is there a more elegant way that makes javascript ignore this line of code if one of these elements doesn't exist?

PS: If one of these elements doesn't exist, the following ones won't either. So if MyElement1 exists, but MyElement2 doesn't, then MyElement3, MyElement4 etc won't exist either.

Also I try to avoid large chunks of code like using an if for each one of these elements

DudeWhoWantsToLearn
  • 751
  • 2
  • 10
  • 29
  • 1
    You ever hear of the if function? Just check if the element exists if(document.getElementById("MyElement1")) { document.getElementById("MyElement1").checked = false; } – Thallius May 18 '21 at 09:22
  • This is a not really elegant way of solving this – DudeWhoWantsToLearn May 18 '21 at 09:23
  • 2
    Make sure your code only works with elements that exist? I'm not sure what sort of elegance you want here - the problem is that you're trying to interact with DOM that doesn't exist (yet?), so...why do that at all? If the DOM *doesn't* exist, then trying to prevent errors just means you still have an issue in your code - it doesn't *work*. At best you've made it not throw errors but still doesn't do what you want. – VLAZ May 18 '21 at 09:25
  • The elegance usually starts from the point where you're not using `document.getElementById` at all. – Teemu May 18 '21 at 09:28
  • Basically I have 5 checkboxes, one for each day of the week. Boxes that have days in the past get ignored, so for example on wednesday I have checkboxes for Wednesday, Thursday and Friday. But I don't want to change the javascript, so I keep the getElementByID for Monday and Tuesday. But it should ignore them if they don't exist – DudeWhoWantsToLearn May 18 '21 at 09:29
  • 3
    Doesn't seem like you want IDs at all. Just select your checkboxes and interact with the ones that *are* on the page: `document.querySelectorAll("input[type='checkbox']").forEach(input => { /* do stuff */})` – VLAZ May 18 '21 at 09:31
  • 1
    At first, group all the days with a class, then mark the days in the past with another class, and collect all the elements with day class but without past class using `querySelectorAll`. If a specific element is not on the page, it's simply not collected, no `id`s are needed. – Teemu May 18 '21 at 09:31
  • @VLAZ This is the most perfect solution I've ever gotten. Didn't even know about this. Thanks very much! – DudeWhoWantsToLearn May 18 '21 at 09:35
  • The world is going crazy. And you really think this is better readable then a simple if statement? I am too old for this job – Thallius May 18 '21 at 09:41
  • @ClausBönnhoff Why not let the machine do the hard job? You don't have to check the existence of an element when you're automatically getting a collection of the existing elements on the page ... – Teemu May 18 '21 at 09:45
  • @ClausBönnhoff I'm with Teemu. You normally want as few code as possible. Also what if I add like 25 more checkboxes because someone wants to have one for every day per month. should I write 30 if-else statements? – DudeWhoWantsToLearn May 18 '21 at 11:03

5 Answers5

3

If I were you, I would do the following:

  1. Add a common class name (say myElement) to all the elements.
  2. Use document.getElementsByClassName to retrieve all the elements in one go.
  3. Iterate them to set checked value of returned elements

Solution would be similar to below:

//previous code
const els = document.getElementByClassName("myElement");
Array.from(els).forEach((el) => { el.checked = false; });
...
//rest of the code
Pavan J
  • 353
  • 1
  • 3
  • 12
  • [Good to know](https://stackoverflow.com/a/66480319/1169519) about iterating live collections, I'd recommend `querySelectorAll` instead of `getElementsByClassName`. – Teemu May 18 '21 at 09:53
  • @Teemu I won't disagree to you! Thanks for the comment. Though both ways work! – Pavan J May 21 '21 at 06:35
2

Using a conditional might do the trick for you. If MyElement exists, this snippet changes the checked value for it, if it doesn't exist it changes the value of a dummy object.

(document.getElementById("MyElement") || {}).checked = false

function check(value)
{
  (document.getElementById("MyElement") || {}).checked = value;
  (document.getElementById("MyElement2") || {}).checked = value; // Doesn't exist but is OK
}
<input type="checkbox" id="MyElement" value="1"></input>
<input type="button" onclick="check(true)" value="Check it"></input>
<input type="button" onclick="check(false)" value="Uncheck it"></input>
Jim Nilsson
  • 838
  • 4
  • 12
0

kind of if statement

document.getElementById("MyElement1") && (document.getElementById("MyElement1").checked = false);

if element exists then document.getElementById("MyElement1") will be result in true due to the && condition, and JS will execute the assignment only if element exists.

Harsh Mehta
  • 141
  • 5
0

I do not know if this is the best way to do it. However, I would approach it this way.

<div id="example">
 <span>I exist</span>
</div>

<div id="result">
 No result yet.
</div>
<div id="result2">
 No result2 yet.
</div>

function isInPage(node) {
  return (node === document.body) ? false : document.body.contains(node);
}
let result = document.getElementById('result')
let result2 = document.getElementById('result2')

const test = document.getElementById('example')
const hello = document.getElementById('hello')
result.innerText = isInPage(test)
result2.innerText = isInPage(hello)
console.log(isInPage(test))

Read more about the API here

Dharman
  • 30,962
  • 25
  • 85
  • 135
damisparks
  • 93
  • 1
  • 10
0

I don't think there's any problem doing try catch, it is one of the standard ways and using it to apply logic is no harm.

Richard Onslow Roper
  • 5,477
  • 2
  • 11
  • 42
  • 1
    You shouldn't use `try`/`catch` as flow control. It's for handling problems. And if you have a *persistent* problem, then `try`/`catch`-ing it is not a solution. If you cannot react in any way to the error, then don't `try`. – VLAZ May 18 '21 at 09:59
  • If we need to create a method that takes in a two dimensional array as a parameter, and prints out its elements, then I don't reckon there is any harm in using try and catch. Infinite loops can be used in such a method and when there is no element at a specific position then trying to print it will throw an exception, which we can handle in the catch block by breaking the loop – Richard Onslow Roper May 18 '21 at 16:14
  • Because the dimensions of the array are not explicitly passed in as parameters to the method, and anyway unless there are any performance or efficiency issues, I don't think using any kind of logic will be objectionable – Richard Onslow Roper May 18 '21 at 16:15
  • That...sounds like horrible implementation. Infinite loop for a 2D array? We can very confidently iterate only over existing indexes. Three simple and quick implementations: [one](https://jsbin.com/hafavit/1/edit?js,console), [two](https://jsbin.com/kolobov/1/edit?js,console), [three](https://jsbin.com/nupedis/1/edit?js,console). Even with this aside: throwing an error in order to call `break`? We can already check if the element is there or not then skip or break as appropriate. Both the reasons you cite are not really valid for using `try`/`catch` in a very simple loop. – VLAZ May 18 '21 at 16:25