Aabha · Learn by building

Explained solution 06: Render a safe, usable filter

A: change notification → listener callback → read select.value → filter events → create/append cards → update count. Filtering is data work; replacing children changes the DOM.

B: textContent makes the fixture title literal text. innerHTML would parse its tags. Avoid treating an untrusted title as markup. This does not solve every kind of unsafe attribute or URL; it solves this text insertion need.

C: add <label for="search">Search titles</label><input id="search" type="search">, then use one shared refresh function:

const search = document.querySelector("#search");
function refresh() {
  const query = search.value.trim().toLowerCase();
  const selected = category.value;
  const visible = events.filter((event) => {
    return event.title.toLowerCase().includes(query)
      && (selected === "all" || event.category === selected);
  });
  renderEvents(visible);
}
search.addEventListener("input", refresh);
category.addEventListener("change", refresh);
refresh();

Replace the old category listener rather than adding a second redundant one. Do not recreate the search input while rendering the list. The full combined filter is also in capstone/reference/core.js.

Return to the exercise