Ошибка из-за того, что элемент пока не существует
У меня на странице выводится таблица. Если в ней больше 3 строк, то средствами PHP в HTML также выводится кнопка "Показать ещё". Проблема в том, что сейчас у меня всего 2 строки, и поэтому в браузере я получаю ошибку: Uncaught TypeError: document.querySelector(...) is null
Урезанный код кнопки:
document.querySelector('#showmore').onclick = function() {
...
}
И как мне быть, в случае, если я любитель делать всё в лучшем виде? Только через оборачивание?:
if (document.querySelector('#showmore') !== null) {
document.querySelector('#showmore').onclick = function() {
...
}
Может есть способ получше? (без обходных путей по типу: "да просто выводи кнопку скрытой при любом количестве строк").
Ответы (5 шт):
В порядке бреда так:
let button = document.querySelector('#showmore');
if (button)
{
button.addEventListener('click', function(){
...
});
}
Если есть препроцессор или новейшие браузеры только, то можно так:
document.querySelector('#showmore')?.addEventListener( 'click', ()=>{
// ...
});
Пара извращенных функций для разнообразия)
(Конечно, лучше использовать более простые решения, но кому-то было скучно).
1: Найти и вернуть элемент, если он есть, или создать (затратная операция!) и подсунуть div, чтобы избежать ошибки. Код применится к созданному div, который вскоре удалится из-за отсутствия ссылок на него.
safe("#moo").addEventListener("click", Function);
safe("#foo").textContent = "ok";
function safe(selector) {
return document.querySelector(selector) || document.createElement("div");
}
<div id="foo"></div>
2: Разместить код, зависимый от селектора, в функцию:
execFor("#foo", function() {
// Весь ваш код, который должен запускаться только при наличии элемента.
// this - найденный элемент.
this.addEventListener("click", function() {
console.log("Ура!");
});
});
execFor("#moo", () => console.log("Не вызывается"));
/***/
function execFor(selector, fn) {
let node = document.querySelector(selector);
if (node && fn) fn.call(node);
// Функция вызывается в контексте найденного элемента,
// Но только если он существует.
return node;
}
<button id="foo"> Click </div>
Самый нормальный способ - это проверить явно:
const showMoreNode = document.querySelector('#showmore');
if (showMoreNode !== null) {
showMoreNode.onclick = function() {
...
}
Можно ещё сделать через делегирование событий:
document.addEventListener('click', ({ target }) => {
if (target.matches('#showmore, #showmore *')) {
console.log('hello');
}
});
Или вообще через атрибут:
<button id="showmore" onclick="showMore()">Show more</button>
function showMore() {
}
Я, как автор вопроса, хочу спросить, как вам такое моё решение? :
const buttonShowMore = document.querySelector('#showmore') ? document.querySelector('#showmore') : new Object();
buttonShowMore('#showmore').onclick = function() {
...
}
Или можно ещё короче:
(document.querySelector('#showmore') ? document.querySelector('#showmore') : {}).onclick = function() {
...
}
Или совсем коротко:
(document.querySelector('#showmore') || {}).onclick = function() {
...
}