How can I get my baby name generator to get results?
I was following a tutorial…and this is my first time using javascript. Help is supremely tremendously appreciated.
How can I get my baby name generator to get results?
I was following a tutorial…and this is my first time using javascript. Help is supremely tremendously appreciated.
Someone said this was the answer, however, when I tried it it did not work…I don’t know what to omit.
By changing these lines:
const setRandomName = () => {
document.getElementById('random-name').innerText = getRandomName();
};
const elements = document.getElementsByClassName('generate')
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', setRandomName);
}
And changing your html to:
<div id="random-name"
class="random-name"></div>
Well let’s take a look at what the console tells us is the problem.
Here’s what the codePen console says:
Uncaught TypeError: document.getElementsByClassName(...).addEventListener is not a function
at https://cdpn.io/cp/internal/boomboom/pen.js?key=pen.js-e41d91d2-6507-ff3d-d73e-1ac7bb534f11:20
Now normally, addEventListener is a function, so the thing causing the problem is that which is before the addEventListener.
Here’s the appropriate piece of code where the trouble is happening:
document
.getElementsByClassName("generate")
.addEventListener("click", setRandomName);
The part before addEventListener is getElementsByClassName. When that isn’t found it becomes undefined, which is why addEventListener isn’t being found.
The problem though is that getElementsByClassName gives list of elements, and addEventListener can’t be applied to such a list.
A good solution to that is to use querySelectorAll instead of getElementsByClassName. That way the querySelectorAll gives a nodeList that can be iterated over, resulting in an easy solution.
Let’s replace getElementsByClassName with querySelectorAll, and then use the forEach method to iterate over each of those elements.
querySelector and querySelectorAll are more flexible, so you prefix the name with a fullstop for a class, or a hash symbol for an id, or leave it blank for an HTML element.
const elements = document.querySelectorAll(".generate");
elements.forEach(function (element) {
element.addEventListener("click", setRandomName);
});
The next problem is harder to find, so let’s try to understand what the code is doing.
The addEventListener is to set a random name, and after that we also set a random name, even though the gender is not known? I’ll remove that second set random name, to avoid any conflict there.
elements.forEach(function (element) {
element.addEventListener("click", setRandomName);
});
// setRandomName(); delete line
We now have a less confusing situation, where we click on boy or on girl, and expect something to occur. It looks like nothing’s happening though, so let’s confirm that set random name is happening.
We can temporarily add a console.log statement to reassure us that the function runs when it should do.
const setRandomName = () => {
console.log("set random name");
document.getElementsByClassName("random-name").innerText = getRandomName();
};
Now when we click on boy or girl, we have set random name
showing on the console, so we know that the function is being invoked. Nothing happens on the page though.
The getElementsByClassName gives an array-like collection of elements, which is not appropriate here. There is only one generate element, and we don’t plan to have more of them.
The HTML element has a id attribute on it, which is a much more suitable way of accessing a single element.
<div id="random-name" class="random-name"></div>
We can replace getElementsByClassName with getElementById instead, to get that random-name element.
We don’t need that console.log line now either, so that can be deleted too.
const setRandomName = () => {
// console.log("set random name"); delete line
document.getElementById("random-name").innerText = getRandomName();
};
And now it all works.
I see in your JS code that you are using several arrow functions. Those are most useful when used as a single one-liner. If you need more than that, arrow notation ends up becoming confusing.
It’s become something of a standard these days to use one-liner arrow notation, and when support for multiple lines is wanted to use a function declaration instead.
Here is arrow-notation that supports multiple lines, even though it has only a single line inside of the braces. This style of arrow notation with the braces is best avoided because it is added complexity with no real benefit from arrow notation.
const setRandomName = () => {
document.getElementById("random-name").innerText = getRandomName();
};
A single-line arrow-notation looks like this:
const setRandomName = () => document.getElementById("random-name").innerText = getRandomName();
But even that’s too long, so let’s assign the random-name element separately:
const randomName = document.getElementById("random-name");
const setRandomName = () => randomName.innerText = getRandomName();
That is a much more appropriate use of arrow notation.
Here’s how that looks as a function declaration:
function setRandomName() {
const randomName = document.getElementById("random-name");
randomName.innerText = getRandomName();
}
I put that in there but codepen keeps saying there isn’t an error but keeps showing a red exclamation mark. this has taken me 3 weeks. What am i doing wrong?
The addEventListener is assigning setRandomName, but that doesn’t yet exist because setRandomName is below that code.
const elements = document.querySelectorAll(".generate");
elements.forEach(function (element) {
element.addEventListener("click", setRandomName);
});
const setRandomName = () => {
document.getElementById("random-name").innerText = getRandomName();
};
Move the setRandomName code up above the addEventListener code, and that will resolve the issue.
const setRandomName = () => {
document.getElementById("random-name").innerText = getRandomName();
};
const elements = document.querySelectorAll(".generate");
elements.forEach(function (element) {
element.addEventListener("click", setRandomName);
});
Can someone put it in the codepen to end my retarded ness this is tormenting lol. never mind it works. ffs who said this was for beginners. T_T
Thank you for helping me, definitely saving this for later. Thank you paul.
If this is the tutorial that you were working from, then that one is not for beginners. That series is for “junior developers” who are people that have been programming for several years already.
Does anyone here have advice about suitable learning resources for JS beginners?
Quick google search, google lied to me! But I have educative membership now. Thank you so much paul, G.O.A.T.
This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.