I get undefined like shown on the picture, when I attach filterByTypes function to onclick on my button. It worked correctly before I started to use webpack. Maybe my syntax is not correct.
function filterByTypes(type) {
console.log(type)
getBookmarks(type)
const buttons = document.querySelectorAll('.button')
for (let i = 0; i < buttons.length; i ) {
if (buttons[i].dataset.id === type) {
buttons[i].classList.add('highlight')
} else {
buttons[i].classList.remove('highlight')
}
}
}
export function generateOptionsAndFilters() {
for (let i = 0; i < types?.length; i ) {
sourceType.innerHTML =
`<option value=${types[i].value}>${types[i].selectName}</option>`
filterStrip.innerHTML =
`<button onclick="${filterByTypes(`${types[i].value}`)}" data-id=${types[i].value}>${types[i].selectName}</button>`
}
}
CodePudding user response:
Template strings are syntax for generating strings.
Inside the template, ${filterByTypes(
${types[i].value})}
means "Call filterByTypes
with the given argument right now and put the return value in the resulting string.
filterByTypes
has no return
statement, so it returns undefined
.
If you want to generate an onclick attribute, then you need to put the JavaScript source code you want in the resulting string instead.
You'll end up with something along the lines of:
onclick="filterByTypes(${escapeHTML(JSON.stringify(types[i].value))})"
Note this uses the escapeHTML
function from this answer.
I do not recommend this as it is fragile, has scoping issues, can be vulnerable to XSS attacks, and is hard to debug.
Generating your DOM using DOM methods instead of mashing strings of HTML together is safer.
export function generateOptionsAndFilters() {
for (let i = 0; i < types?.length; i ) {
const option = document.createElement('option').
option.textContent = types[i].selectName;
option.value = types[i].value;
sourceType.appendChild(option);
const button = document.createElement('button');
button.className = "button";
button.setAttribute('data-id', types[i].value);
button.textContent = types[i].selectName;
button.addEventListener("click", () => filterByTypes(types[i].value));
filterStrip.appendChild(button);
}
}
CodePudding user response:
Might be additional back ticks. Try this
filterStrip.innerHTML = `<button onclick="${filterByTypes(${types[i].value})}" data-id=${types[i].value}>${types[i].selectName}</button>`