0

I am trying to add an active class to a div by means of a data id. Currently clicking on it does nothing and I get no errors in console. The data is generated with jQuery ie: dynamic data so not sure if that has something to do with it. So, when the page loads, data is fetched from an api and the html output is rendered with javascript. There are multiple card divs inside the columns div, they just have different data id's.

$('.columns').append(cardData);

$(".columns .card[data-id='" + id + "']").addClass('active');
user8463989
  • 2,275
  • 4
  • 20
  • 48
  • 1
    Please include the relevant html and jquery – Carsten Løvbo Andersen Sep 21 '22 at 10:09
  • Is the `.columns` element pre-defined on the page before the cards are added, or is that added dynamically too? – Andy Sep 21 '22 at 10:10
  • @Andy `.columns` is already there and the data is appended to that. – user8463989 Sep 21 '22 at 10:16
  • @user8463989 consider providing a [mcve] so we can reproduce your issue and try to find solutions. – ThS Sep 21 '22 at 10:20
  • data/html being generated dynamically (after the page loads) is only relevant if your code runs before the elements exist - particularly for event binding, but not limited to. If `console.log($(".columns").length)` is non-zero just before your code runs, then that's not relevant. – freedomn-m Sep 21 '22 at 10:26
  • Extrapolating HTML/CSS from your jquery, your code works fine: https://jsfiddle.net/y4nvbejk/ if it's not working on your page then there's something *that you've not included in the question* - maybe the `id` value doesn't match the HTML? Maybe you don't have an active css? Whatever it is , it's not your selector/addClass (the bit you *did* include). Please add a complete snippet that demonstrates the issue. See [mcve]. – freedomn-m Sep 21 '22 at 10:29
  • This may be a case of your code running before the ajax call has completed, a common case of : `$.ajax(...); $(..).addClass(..)` rather than being in the ajax complete callback: `$.ajax(...).done(() => $(..).addClass(..))` so please also include that code. – freedomn-m Sep 21 '22 at 10:31
  • More details / possible duplicate: https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call – freedomn-m Sep 21 '22 at 11:16

1 Answers1

1
  1. You obviously need to wait until the HTML has been requested and added to the page.

  2. You need to access the cards by data-id within the element containing the columns class.

This example uses find to locate the card with the specified id within the .columns element.

// Mock API request to deliver HTML
function mockApi() {
  return new Promise(res => {
    setTimeout(() => {
      res(`
        <div class="card" data-id="1">1</div>
        <div class="card" data-id="2">2</div>
        <div class="card" data-id="3">3</div>
        <div class="card" data-id="4">4</div>
    `);
    }, 1000);
  });
}

// Cache the columns element
const columns = $('.columns');

// Append HTML to the columns element
function appendHtml(html) {
  columns.append(html);
}

// Accept an id, use that within a selector
// and then use that with `find` to select the
// appropriate card, and update its class.
function updateCard({ id }) {
  const selector = `.card[data-id='${id}']`;
  const el = columns.find(selector);
  el.addClass('active');
}

// Get the data, update the DOM, and
// then update the card
async function main() {
  const html = await mockApi();
  appendHtml(html);
  updateCard({ id: 2 });
}

main();
.active { background-color: #efefef; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="columns"></div>
Andy
  • 61,948
  • 13
  • 68
  • 95
  • 1
    Thanks so much for the responses. It seems it was me being a muppet as the code was not working because there was not enough time for the Ajax data to load. It doesn't load on page load, but when a button is clicked. So, the button was clicked and the active class was not added because the results had not loaded yet. I used a timeout to wait a few seconds before adding the class and it works perfectly. @Andy, I prefer your code so have adopted some of it. Thanks! – user8463989 Sep 21 '22 at 10:59
  • 1
    You probably don't need a timeout since [jQuery's AJAX method(s)](https://api.jquery.com/jquery.ajax/) return a promise which you can `await` like I've done here, or you can use `then`/`done` to wait until the request has completed before you add the HTML to the DOM. – Andy Sep 21 '22 at 11:02