简体   繁体   中英

Why is the input value of the new object is undefined?

I want to get the values in the form inputs and create a new song object inside the "songs" array. I am trying to make a music app just for fun, but I got stuck. Here is my HTML code

 <,DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width. initial-scale=1.0"> <script src="music.app.js"></script> <link rel="stylesheet" href="music.app.try.css"> <title>Music App</title> </head> <body> <div class="add-song-continer" id="add-song-continer"> <form id="add-song-form"> <button class="close-btn" id="close-add-song">X</button> <h1 class="h1-add-Song" >Add your song </h1> <br> <input type="text" class="song-name-add" placeholder="Song Name" value=""><br> <br> <input type="text" class="artist-name-add" placeholder="Artist Name"><br> <br> <input type="text" class="albom-name-add" placeholder="Albom Name"><br> <br> <input type="text" class="mp3-file-add" placeholder="Song File"><br> <br> <input type="text" class="img-add" placeholder="Image"><br> <button class="add-song-btn" id = "add-song-btn"> Add Song</button> </form> </div> </body> </html>

Here is the CSS code

 .add-song-continer { margin:0; background-color: #FFF; position: fixed; display: flex; top:20%; left:50%; width:45%; min-width: 250px; max-width: 250px; height: 460px; border: 1px solid black; box-shadow: 0.5rem 1rem 2rem grey; transform:translateX(-50%) translateY(00%) }.add-song-continer input{ margin-left: 2.5rem; margin-bottom: 0rem; padding: 0.5rem; background-color: rgb(241, 239, 239); border: 1px solid gray; }.add-song-continer label{ margin: 2.5rem; padding-top: 1rem; }.add-song-continer h1{ margin: 1rem; padding: 0.5rem; text-align: center; }.add-song-btn{ position: relative; margin: auto; margin-top: 5%; margin-bottom: 10%; padding: 0.4rem; left: 50%; background: linear-gradient(to right, #66ccff 0%, #cc99ff 100%); border:1px solid lightgrey; border-radius: 3px; transform: translateX(-50%); animation: grediant-add-song 0.7s ease-out 0s infinite; }.close-btn { margin: 2%; margin-top: -4%; padding: 0.4rem 0.4rem; position: relative; float: right; background-color: tomato; border-radius: 3px; border: none; box-shadow: 1 1 1 gray; } @keyframes grediant-add-song { 0% {background: linear-gradient(to right, #66ccff 0%, #cc99ff 100%)} 12.5% {background: linear-gradient(to right bottom, #66ccff 0%, #cc99ff 100%)} 25% {background: linear-gradient(to bottom, #66ccff 0%, #cc99ff 100%)} 37.5% {background: linear-gradient(to bottom left, #66ccff 0%, #cc99ff 100%)} 50% {background: linear-gradient(to left, #66ccff 0%, #cc99ff 100%)} 62.5% {background: linear-gradient(to left top, #66ccff 0%, #cc99ff 100%)} 75% {background: linear-gradient(to top, #66ccff 0%, #cc99ff 100%)} 87.5% {background: linear-gradient(to top right, #66ccff 0%, #cc99ff 100%)} 100% {background: linear-gradient(to right, #66ccff 0%, #cc99ff 100%)} }

Here is the JavaScript code

 let songs = []; const AddSongFunction = (ev) => { ev.preventDefault(); let song = { name: document.getElementsByClassName("song-name-add").value, artist: document.getElementsByClassName("artist-name-add").value, albom: document.getElementsByClassName("albom-name-add").value, fill: document.getElementsByClassName("mp3-file-add").value, img: document.getElementsByClassName("img-add").value }; songs.push(song); document.querySelector("form").reset(); console.log(songs); } document.addEventListener("DOMContentLoaded", () => { document.getElementById("add-song-btn").addEventListener("click", AddSongFunction ) });

I just can't figure It Out, if someone can show what went wrong I will be grateful. PS it is my first question so I hope it's understandable. Thank you all (:

That's because getElementsByClassName return's a HTMLCollection, the "value" property can be obtained only on a HTMLElement. So you can select an element by it's position on that collection like:

let song = { 
      name: document.getElementsByClassName("song-name-add")[0].value, 
      artist: document.getElementsByClassName("artist-name-add")[0].value,
      albom: document.getElementsByClassName("albom-name-add")[0].value,
      fill: document.getElementsByClassName("mp3-file-add")[0].value,
      img: document.getElementsByClassName("img-add")[0].value
      };

This returns an array:

document.getElementsByClassName("song-name-add");

This is because classes are expected to be reusable. If you want this to return a specific value try using

<input type="text" id="song-name-add" placeholder="Song Name">

and

document.getElementById("song-name-add");

Or if you specifically want to use classes, you can get the value of the first object with that class using

document.getElementsByClassName("song-name-add")[0].value;

You are using getElementsByClassName, its return value is an array. If you want to access its value, you have to use its index document.getElementsByClassName("song-name-add")[0].value or loop on the Array

You need to use document.querySelector() instead of document.getElementsByClassName(). querySelector().value returns the value of the input box, while getElementsByClassName() returns collection just like an array. You can in your case use getElementsByClassName().value[0] but better is to use querySelector() only.

Here is the updated song object:

   let song = {
      name: document.querySelector(".song-name-add").value,
      artist: document.querySelector(".artist-name-add").value,
      albom: document.querySelector(".albom-name-add").value,
      fill: document.querySelector(".mp3-file-add").value,
      img: document.querySelector(".img-add").value,
    };

One quick Tip: Avoid using script tag in the head because is blocking the HTML to load until all the script loads.

<script src="music.app.js"></script>

Either put it above the closing </body> tag, or use async property in the script tag used in the <head> element.

<script async src="music.app.js"></script>

It makes your script non-blocking

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM