I am trying to edit/update current data using the contenteditable attribute which I have successfully enabled onclick. My 'enter' key allows the data to be submitted. However, the console.log reads that a PUT request has been made for a particular list item but without the 'title' or 'isbn' being updated along with it.
Another prominent issue is that my console.log shows books.forEach is not a function
, and I have no idea why this is the case since the code inside that function is processed.
HTML ('li' items are solely JS-Generated with a POST request)
<div id="divShowBooks">
<li id="[object HTMLParagraphElement]">
<p id="24" name="anID" placeholder="24">1</p>
<p id="TEST" name="aTitle" placeholder="TEST">TEST</p>
<p id="12345" name="anISBN" placeholder="12345" contenteditable="true">12345</p>
<button>Delete</button>
</li>
</div>
JavaScript
var book_list = document.querySelector('#divShowBooks');
book_list.innerHTML = "";
var books = JSON.parse(this.response);
books.forEach(function (book) {
// Text information to be displayed per item
var id = document.createElement('p');
id.type = 'text';
id.innerHTML = book.id;
var title = document.createElement('p');
title.type = 'text';
title.innerHTML = book.title;
var isbn = document.createElement('p');
isbn.type = 'text';
isbn.innerHTML = book.isbn;
// Defining the element that will be created as a list item
var book_item = document.createElement('li');
// Displays id, title and ISBN of the books from the database
book_item.appendChild(id);
book_item.appendChild(title);
book_item.appendChild(isbn);
// Creates an ID attribute per list item
book_item.setAttribute("id", id)
// Assigns attributes to p items within book items
id.setAttribute("id", book.id)
title.setAttribute("id", book.title)
isbn.setAttribute("id", book.isbn)
// Adding a generic name to these elements
id.setAttribute("name", "anID")
title.setAttribute("name", "aTitle")
isbn.setAttribute("name", "anISBN")
title.addEventListener('click', function (e) {
e.preventDefault();
title.contentEditable = "true";
title.setAttribute("contenteditable", true);
title.addEventListener('keypress', function (e) {
if (e.keyCode === 13) {
e.preventDefault();
xhttp.open("PUT", books_url + '/' + book.id, true);
var editTitle = new FormData() /
editTitle.append("title", document.getElementsByName("aTitle")[0].value)
xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
xhttp.send(); //
}
});
});
UPDATE
I have added the following to my code. This seems to display my database items as an array in the log. But, I am now having a similar issue with Uncaught TypeError: JSON.parse(...).map is not a function
:
var params = [
id = 'id',
title = 'title',
isbn = 'isbn',
createdAt = 'createdAt',
updatedAt = 'updatedAt'
];
var books = JSON.parse(this.response).map(function(obj) {
return params.map(function(key) {
return obj[key];
});
});
console.log(books);
UPDATE 2
Here is an image of what I receive in the console.log. The first part displays the original JSON content and the second is my attempt to convert each object into an array.
You have to make sure that your books
variable actually contains an Array after parsing.
Alternatively, but this wouldn't make sense, just to address the "books.forEach is not a function" issue, You can use Object.assign([], this.response);
. To make sure that books
will contain an array, you wrap it in a try catch and make something like this:
var books = [];
try {
books = Object.assign([], this.response);
} catch (error) {
books = [];
}
books.forEach
will then be expected to always work but you have to be careful because something like this could happen:
var myStringObject = "{'myProperty':'value'}";
var myArray = Object.assign([], myStringObject );
//myArray value is ["{", "'", "myProperty", "'", ":", "'", "value", "'", "}"]
Which will leave you having to check the book
in your forEach
callback if it is correct:
//at the topmost of your forEach callback
if(!book.id) throw BreakException; //A simple break will not work on forEach
This will leave you again with another exception to handle. Or leave you having to use the traditional for
loop since you cannot short circuit Array.forEach with a break.
TLDR: make sure books
always contains an Array.