All I'm doing was getting the tbody tag from my html code using the document.getElementByID("tableBody") and trying to add some rows using the javascript. But whenever I try to set the innerHTML property of the tbody tag, it shows me this error.
index2.js:38 Uncaught TypeError: Cannot set properties of null (setting 'innerHTML')
at Display.add (index2.js:38)
at HTMLButtonElement.<anonymous> (index2.js:90)
I don't know why I'm getting this error I've revisted my code multiple times. Please help someone
HTML code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Reading</title>
<!-- CSS of the bootstrap -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="CSS/style.css">
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Leckerli One&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=IBM Plex Serif:wght@400;700&display=swap" rel="stylesheet">
<!-- Fontawesome cdn -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css" integrity="sha384-DyZ88mC6Up2uqS4h/KRgHuoeGwBcD4Ng9SiP4dIRy0EXTlnuz47vAwmeGwVChigm" crossorigin="anonymous">
</head>
<body>
<!-- Navbar Code -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a href="#" class="navbar-brand navbar-expand-lg navbar-dark bg">READINGS</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarTogglerDemo01"
aria-controls="navbarTogglerDemo01" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div id="navbarTogglerDemo01" class="collapse navbar-collapse">
<ul class="navbar-nav mr-auto">
<li class="nav-item"> <a href="#" class="nav-links">Home</a></li>
</ul>
</div>
</nav>
<!-- library detail code starts -->
<div class="container-fluid form-section">
<h1>My Reading Library</h1>
<!-- Form section -->
<div class="container form-holder-div">
<form id="libraryForm">
<div class="form-group row">
<label for="bookName" class="col-sm-2 col-form-label">Book Name</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="bookName">
</div>
</div>
<div class="form-group row">
<label for="AuthorName" class="col-sm-2 col-form-label">Author of the book</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="authorName">
</div>
</div>
<fieldset class="form-group row">
<legend class="col-form-label col-sm-2 float-sm-left pt-0">Type</legend>
<div class="col-sm-10">
<div class="form-check">
<input class="form-check-input" type="radio" name="bookType" id="Fiction" value="fiction"
checked>
<label class="form-check-label" for="fiction">
Fiction
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="bookType" id="Programming"
value="programming">
<label class="form-check-label" for="Programming">
Programming
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="bookType" id="Cooking" value="cooking">
<label class="form-check-label" for="Cooking">
Cooking
</label>
</div>
</div>
</fieldset>
<div class="form-group row">
<div class="col-sm-10">
<button type="submit" class="btn btn-primary" style="font-weight: 700;" id="addButton">Add Book</button>
</div>
</div>
</form>
</div>
</div>
<!-- table section -->
<div class="container-fluid table-section" id="tableArea">
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">#</th>
<th scope="col">Book Name</th>
<th scope="col">Author Name</th>
<th scope="col">Type</th>
<th scope="col">Operation</th>
</tr>
</thead>
<tbody id="tableBody">
</tbody>
</table>
</div>
<div class="footer-section">
<h1><i class="far fa-copyright"> </i> Made with <i class="far fa-laugh-wink"></i> by TheNullPerson</h1>
</div>
<!-- This is the bootstrap javaScript -->
<script src="javascript/index2.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.slim.min.js"
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C OGpamoFVy38MVBnE IbbVYUew OrCXaRkfj"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js"
integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU 6BZp6G7niu735Sk7lN"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"
integrity="sha384-VHvPCCyXqtD5DqJeNxl2dtTyhF78xXNXdkwX1CZeRusQfRKp tA7hAShOK/B/fQ2"
crossorigin="anonymous"></script>
</body>
</html>
JavaScript code:
var bookObj = [];
/* Display Class with the following methods:
1) .add(book) => to add book(array of book objects) to the table element
2) .clear => to clear the element from the text fields
*/
function Display() {
}
// .add() method
Display.prototype.add = function () {
let bookElements = localStorage.getItem("books");
if (bookElements === null) {
bookObj = [];
} else {
bookObj = JSON.parse(bookElements);
console.log(typeof bookObj);
}
console.log(bookObj);
let html = "";
let Element;
if (bookObj.length === 0) {
html = "<h1>Please add some content from above section</h1>";
Element = document.getElementById("tableArea");
Element.innerHTML = html;
} else {
bookObj.forEach(function(element, index) {
html = `<tr>
<th scope="row">${index 1}</th>
<td>${element.bookName}</td>
<td>${element.authorName}</td>
<td>${element.type}</td>
<th scope="col"> <button > Remove </button> </th>
</tr>`;
});
Element = document.getElementById("tableBody");
// console.log(typeof tableElement);
Element.innerHTML = html;
}
html = "";
}
// .clear() method
Display.prototype.clear = function(){
let form = document.getElementById("libraryForm");
form.reset();
}
var display = new Display(); // Display object to access different display methods
display.add();
display.clear();
/*
Book class with the property
1) bookName = Name of the book
2) authorName = Name of the author
3) type = Type of book
*/
function Book(bookName, authorName, type){
this.bookName = bookName;
this.authorName = authorName;
this.type = type;
}
let addBook = document.getElementById("addButton");
addBook.addEventListener("click", function (e){
e.preventDefault();
let bookName = document.getElementById("bookName").value;
let authorName = document.getElementById("authorName").value;
let type;
let fiction = document.getElementById("Fiction");
let programming = document.getElementById("Programming");
let cooking = document.getElementById("Cooking");
if (fiction.checked){
type = fiction.value;
} else if (programming.checked) {
type = programming.value;
}
else if (cooking.checked) {
type = cooking.value;
}
let book = new Book(bookName, authorName, type);
bookObj.push(book);
// console.log(typeof book)
localStorage.setItem("books", JSON.stringify(bookObj));
console.log(typeof bookObj);
display.add();
display.clear();
})
CodePudding user response:
This is because when bookObj
is empty, you obliterate the <div>
that contains the table (and therefore the tbody
).
Then, once you add a book to bookObj
there is no longer a table on the page to find, so Element
is null
.
Consider hiding the content you don't want to appear rather than obliterating it.
var bookObj = [];
/* Display Class with the following methods:
1) .add(book) => to add book(array of book objects) to the table element
2) .clear => to clear the element from the text fields
*/
function Display() {}
// .add() method
Display.prototype.add = function() {
/* let bookElements = localStorage.getItem("books");
if (bookElements === null) {
bookObj = [];
} else {
bookObj = JSON.parse(bookElements);
console.log(typeof bookObj);
}
*/
let html = "";
if (bookObj.length === 0) {
document.querySelector("#tableArea h1").style.display = "block";
document.querySelector(".table").style.display = "none";
} else {
bookObj.forEach(function(element, index) {
html = `<tr>
<td scope="row">${index 1}</td>
<td>${element.bookName}</td>
<td>${element.authorName}</td>
<td>${element.type}</td>
<td scope="col"> <button > Remove </button> </td>
</tr>`;
});
document.getElementById("tableBody").innerHTML = html;
document.querySelector("#tableArea h1").style.display = "none";
document.querySelector(".table").style.display = "block";
}
html = "";
}
// .clear() method
Display.prototype.clear = function() {
let form = document.getElementById("libraryForm");
form.reset();
}
var display = new Display(); // Display object to access different display methods
display.add();
display.clear();
/*
Book class with the property
1) bookName = Name of the book
2) authorName = Name of the author
3) type = Type of book
*/
function Book(bookName, authorName, type) {
this.bookName = bookName;
this.authorName = authorName;
this.type = type;
}
let addBook = document.getElementById("addButton");
addBook.addEventListener("click", function(e) {
e.preventDefault();
let bookName = document.getElementById("bookName").value;
let authorName = document.getElementById("authorName").value;
let type;
let fiction = document.getElementById("Fiction");
let programming = document.getElementById("Programming");
let cooking = document.getElementById("Cooking");
if (fiction.checked) {
type = fiction.value;
} else if (programming.checked) {
type = programming.value;
} else if (cooking.checked) {
type = cooking.value;
}
let book = new Book(bookName, authorName, type);
bookObj.push(book);
// console.log(typeof book)
//localStorage.setItem("books", JSON.stringify(bookObj));
console.log(typeof bookObj);
display.add();
display.clear();
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Reading</title>
<!-- CSS of the bootstrap -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
<!-- Custom CSS -->
<link rel="stylesheet" href="CSS/style.css">
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Leckerli One&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=IBM Plex Serif:wght@400;700&display=swap" rel="stylesheet">
<!-- Fontawesome cdn -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css" integrity="sha384-DyZ88mC6Up2uqS4h/KRgHuoeGwBcD4Ng9SiP4dIRy0EXTlnuz47vAwmeGwVChigm" crossorigin="anonymous">
</head>
<body>
<!-- Navbar Code -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a href="#" class="navbar-brand navbar-expand-lg navbar-dark bg">READINGS</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarTogglerDemo01" aria-controls="navbarTogglerDemo01" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div id="navbarTogglerDemo01" class="collapse navbar-collapse">
<ul class="navbar-nav mr-auto">
<li class="nav-item"> <a href="#" class="nav-links">Home</a></li>
</ul>
</div>
</nav>
<!-- library detail code starts -->
<div class="container-fluid form-section">
<h1>My Reading Library</h1>
<!-- Form section -->
<div class="container form-holder-div">
<form id="libraryForm">
<div class="form-group row">
<label for="bookName" class="col-sm-2 col-form-label">Book Name</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="bookName">
</div>
</div>
<div class="form-group row">
<label for="AuthorName" class="col-sm-2 col-form-label">Author of the book</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="authorName">
</div>
</div>
<fieldset class="form-group row">
<legend class="col-form-label col-sm-2 float-sm-left pt-0">Type</legend>
<div class="col-sm-10">
<div class="form-check">
<input class="form-check-input" type="radio" name="bookType" id="Fiction" value="fiction" checked>
<label class="form-check-label" for="fiction">
Fiction
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="bookType" id="Programming" value="programming">
<label class="form-check-label" for="Programming">
Programming
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="bookType" id="Cooking" value="cooking">
<label class="form-check-label" for="Cooking">
Cooking
</label>
</div>
</div>
</fieldset>
<div class="form-group row">
<div class="col-sm-10">
<button type="submit" class="btn btn-primary" style="font-weight: 700;" id="addButton">Add Book</button>
</div>
</div>
</form>
</div>
</div>
<!-- table section -->
<div class="container-fluid table-section" id="tableArea">
<h1>Please add some content from above section</h1>
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">#</th>
<th scope="col">Book Name</th>
<th scope="col">Author Name</th>
<th scope="col">Type</th>
<th scope="col">Operation</th>
</tr>
</thead>
<tbody id="tableBody">
</tbody>
</table>
</div>
<div class="footer-section">
<h1><i class="far fa-copyright"> </i> Made with <i class="far fa-laugh-wink"></i> by TheNullPerson</h1>
</div>
<!-- This is the bootstrap javaScript -->
<script src="javascript/index2.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C OGpamoFVy38MVBnE IbbVYUew OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU 6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-VHvPCCyXqtD5DqJeNxl2dtTyhF78xXNXdkwX1CZeRusQfRKp tA7hAShOK/B/fQ2" crossorigin="anonymous"></script>
</body>
</html>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
Your code is okay and running well but the reason why you are not seeing the table is that you are assigning two different values to the Element
identifier. Inside the execution context
, where javascript
is executed, the operations are done from top
to bottom
. Your code assigns value to the Element
identifier inside the if condition
after which the element is removed from the execution context.
Your javascript code should look like this after removing the first assignment of the Element identifier
inside the if statement
.
var bookObj = [];
/* Display Class with the following methods:
1) .add(book) => to add book(array of book objects) to the table element
2) .clear => to clear the element from the text fields*/
function Display() {
}
// .add() method
Display.prototype.add = function () {
let bookElements = localStorage.getItem("books");
if (bookElements === null) {
bookObj = [];
} else {
bookObj = JSON.parse(bookElements);
console.log(typeof bookObj);
}
console.log(bookObj);
let html = "";
let Element;
if (bookObj.length === 0) {
html = "<h1>Please add some content from above section</h1>";
Element.innerHTML = html;
} else {
bookObj.forEach(function(element, index) {
html = `<tr>
<th scope="row">${index 1}</th>
<td>${element.bookName}</td>
<td>${element.authorName}</td>
<td>${element.type}</td>
<th scope="col"> <button > Remove </button> </th>
</tr>`;
});
Element = document.getElementById("tableBody");
// console.log(typeof tableElement);
Element.innerHTML = html;
}
html = "";
}
// .clear() method
Display.prototype.clear = function(){
let form = document.getElementById("libraryForm");
form.reset();
}
var display = new Display(); // Display object to access different display methods
display.add();
display.clear();
/*
Book class with the property
1) bookName = Name of the book
2) authorName = Name of the author
3) type = Type of book */
function Book(bookName, authorName, type){
this.bookName = bookName;
this.authorName = authorName;
this.type = type;
}
let addBook = document.getElementById("addButton");
addBook.addEventListener("click", function (e){
e.preventDefault();
let bookName = document.getElementById("bookName").value;
let authorName = document.getElementById("authorName").value;
let type;
let fiction = document.getElementById("Fiction");
let programming = document.getElementById("Programming");
let cooking = document.getElementById("Cooking");
if (fiction.checked){
type = fiction.value;
} else if (programming.checked) {
type = programming.value;
}
else if (cooking.checked) {
type = cooking.value;
}
let book = new Book(bookName, authorName, type);
bookObj.push(book);
// console.log(typeof book)
localStorage.setItem("books", JSON.stringify(bookObj));
console.log(typeof bookObj);
display.add();
display.clear();
})
It works and displays the table on the UI.