-1

I'm new to JS, so I apologize if it's a basic question. My code is the following:

The code is broken. Why does the following error appear in the console:

TypeError: Cannot read properties of null (reading 'style')
    at fe01ce2a7fbac8fafaed7c982a04e229:208
    at Array.forEach (<anonymous>)
    at fe01ce2a7fbac8fafaed7c982a04e229:195

I only want that if the distance is less than 20 the button is shown, if it is the opposite the button is hidden. No matter the method, maybe there is another way to do it, or the solution to my problem.

The problem comes with the CSS. Because if I put the following no error comes out and it does show up fine on the console:

if (distance < 20) {
   console.log("Distance < 20");
  } else {
   console.log("Distance > 20");
 }

What my code does is iterate. @MaikLowrey tells me that it is a problem in the DOM because the buttons are created depending on whether they exist in the iteration. My complete code is:

JS

        const positions = getLugares();
        positions.then((positions) => {
          positions.forEach((position) => {
            //Get lat and lng
            const latitud_lugar = position.location.lat;
            const longitud_lugar = position.location.lng;
            const id_lugar = position.id;

            //Calculate distance between two points
            const distance = getDistanceBetweenPoints(latitud_persona, longitud_persona, latitud_lugar, longitud_lugar);
            console.log("Distancia", distance);
            console.log("Id lugar", id_lugar);

            // Show button with id='recoger-id_lugar' if distance is less than 20 meters and hide it if distance is greater than 20 meters
            // Use DOMContentLoaded to show the button
                        
            if (distance < 20) {
              document.getElementById('recoger-' + id_lugar).style.display = 'block !important';
            } else {
              document.getElementById('recoger-' + id_lugar).style.display = 'none !important';
            }
          
          });
        }).catch((error) => {
          console.log(error);
        });

HTML

<a href='/recoger/{id}/{id_lugar}' id='recoger-{id}' class='btn btn-light recoger hide'>Recoger</a>

Returns all buttons, with their ID. Example:

<a href='/recoger/1/1' id='recoger-1' class='btn btn-light recoger **hide**'>Recoger</a>

CSS

.hide {
    display: none !important;
}  
principemestizo3
  • 161
  • 3
  • 13
  • 1
    If it isn't the typo you say you fixed in a comment on an answer, it's probably a [duplicate](https://stackoverflow.com/questions/14028959/why-does-jquery-or-a-dom-method-such-as-getelementbyid-not-find-the-element) – Quentin Jan 20 '22 at 16:41
  • `getLugares()` is the a api call? – Maik Lowrey Jan 20 '22 at 18:54
  • Yes... a fetch to get the data. – principemestizo3 Jan 20 '22 at 19:00
  • @principemestizo3 The Problem is that your positions object is not filled with data. Because async behavior. Easy and small fix would be to put the forEach loop into the then block from your fetch call. fetch().then(res => res.json()).then(res => ...your loop...).catch(err => {...}) – Maik Lowrey Jan 20 '22 at 19:37

2 Answers2

-1

You can use classList add and remove for this case. You can change distance value to check if pickup link will hiden.

const a = document.getElementById('pick');
const distance = 10;

distance < 20 ? a.classList.remove('hide') : a.classList.add('hide');
.hide {
  display: none;
}
<a href="pick" id="pick" class="btn btn-light hide">Pickup</a>
Maik Lowrey
  • 15,957
  • 6
  • 40
  • 79
  • It was an error when writing the question, in the code I have it correctly. Excuse me. – principemestizo3 Jan 20 '22 at 16:40
  • @principemestizo3 Thanks for hint. I updated my answer. – Maik Lowrey Jan 20 '22 at 16:48
  • TypeError: Cannot read properties of null (reading 'classList') – principemestizo3 Jan 20 '22 at 17:02
  • @principemestizo3 then the problem is in your DOM. It seems that JS cant get then Element with the id pick. check your html. because you see in the example it works. – Maik Lowrey Jan 20 '22 at 17:04
  • While classList is a nicer approach, in general, than directly accessing the `style` property, `null` doesn't have a `classList` property either. – Quentin Jan 20 '22 at 17:04
  • @Quentin I think the client has a problem in his DOM. The error message also confirms the assumption. Because the code in my answer works because it finds the element with the id="pick". If the question owner fixes this bug on his end it should work. I can't do more than point it out here. – Maik Lowrey Jan 20 '22 at 17:09
  • a problem in my DOM? Can you explain me a little more? Please. – principemestizo3 Jan 20 '22 at 17:18
  • @principemestizo3 Yes of course :-) This can have several reasons. Here are the reasons I can think of. 1) Your JS is loaded first, then your DOM is rendered. This means JS cannot access the selectors (`pick`). To avoid that put your js to the end of you html. (above closing /body) 2) there is no selector pick in your HTML. To rule out the latter, open the source code of your html page and search for `"pick"`. – Maik Lowrey Jan 20 '22 at 17:21
  • 1
    You are right, it does not appear in the source code. That button is created after loading the page, because it uses my database to know how many to create. If I have 2 it creates 2, if I have 3 it creates 3. What it does is iterate. I will update this question. Sorry, I didn't think it was necessary (I didn't want to redound with code). – principemestizo3 Jan 20 '22 at 17:23
  • @principemestizo3 cool, then we are already very close to the solution. Your error message also says `at Array.forEach ()` where the problem occurs. – Maik Lowrey Jan 20 '22 at 17:26
  • 1
    Done, I already updated the question. Please check. @MaikLowrey – principemestizo3 Jan 20 '22 at 17:28
-1

Style equals to a string. You should equal to a new string. Like that

if (distance < 20) {
    document.getElementById('pick').style = 'display: block !important';
} else {
    document.getElementById('pick').style = 'display: none !important';
}
Ali Konuk
  • 20
  • 1