How I Did It

In a frenzy of late-night activity, I got my node-sqlite template project to add data to the database. I don’t know exactly how it works, however, since I pulled everything together with a lot of trial and error, based on random examples I found on the internet.

Now it’s time to review what I wrote and build up a deeper understanding of what’s actually going on. Maybe along the way I’ll figure out better ways to accomplish my goal.

The changes I made were pretty simple. On the client side, I expanded the submit button code to include a post request to the server and on the server side I added a way to handle that request.  The tricky part was figuring out how to get that HTTP post request up and running, and how to include the dream’s text string in that request.

Now to review what I did and see what I can do to clean it up.


const newDreamRequest = new XMLHttpRequest();

We’ll start with client.js. I added this line to create a new HTTP request. So far, so good.


var myForm = document.getElementById('myForm');
const form = new FormData(myForm);
const newDream = form.get("dream");

Because I hadn’t really read through my client.js code, I came up with this convoluted way to capture data from the text box. I set up a new variable to hold the HTML element, even though the template already had dreamsForm. Then I used the FormData interface to get the string out of the textbox even though I already had the dreamInput variable with the exact same data. These three lines are completely redundant – oops!


var xhr = new XMLHttpRequest();
xhr.open("POST", '/newDream', true);

This chunk of code creates a new HTTP request and configures it to send a POST method to the ‘/newDream’ URL.

If you were paying attention, you’ll notice that I already created a new HTTP request called newDreamRequest. But then I copied and pasted all this xhr code from the XMLHttpRequest documentation and promptly forgot about that initial request. That makes two thirds of my code unnecessary so far!


xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

This line sets a request header that specifies the content type of the request.  For the content type, the code I copied uses “application/x-www-form-urlencoded” as the content type, which is a fancy way of representing form data. This doesn’t actually make sense for what I’m doing because my form only has one field! All I need to do is send a string. I think the content type I actually need is “text/plain”.


xhr.onreadystatechange = function() {//Call a function when the state changes.
  if(this.readyState == XMLHttpRequest.DONE && this.status == 200) {
    // Request finished. Do processing here.
  }
}

This is a callback function from the example code, but I never added anything to the body of the function (where the comment says “do processing here”). Therefore this function doesn’t do anything and I can take it out completely.


xhr.send("dream=" + newDream);

Because I specified a fancy form content type instead of just a text content type, I have to add “dream=” to my dream text so that it is formatted according to the content type I’m using.


Ok, that covers everything I changed on the client side. Out of 13 lines, only four of them are actually necessary and two of those four are overly complicated.

Let’s see what I did on the server end. I didn’t add as much, so hopefully that means there’s less room for error.


app.post('/newDream', function(request, response){
  console.log(request.body);
  var dream = request.body.dream;
  console.log(dream);
  var sqlStatement = 'INSERT INTO Dreams (dream) VALUES ("' + dream + '")';
  console.log(sqlStatement);
  db.run(sqlStatement);
  response.send("Dream inserted.");
});

The only thing I added to my server.js is this .post() function to handle incoming post requests to the ‘/newDream’ URL. I’ll go through it line by line.


console.log(request.body);

This logs the body of the request to the console so that I can see what’s coming in.  It should match whatever was inside the parentheses of xhr.send();

Here’s what showed up in the console for my latest dream:

{ dream: 'Checking logs...' }

var dream = request.body.dream;
console.log(dream);

This pulls out just the dream value, which is the text string.

In the console it looks like this:

Checking logs...

var sqlStatement = 'INSERT INTO Dreams (dream) VALUES ("' + dream + '")';
console.log(sqlStatement);

I construct my SQL statement that will insert this string into the Dreams table of my database.

The console:

INSERT INTO Dreams (dream) VALUES ("Checking logs...")

db.run(sqlStatement);
response.send("Dream inserted.");

Here I run the SQL statement. The database is now updated, so I send a response message back to the client which is promptly ignored. (I don’t think it would be hard to have the client log the response in its own console. That would be pretty cool!)


In conclusion, my server side code is much more sensible than my client side code. Only a third of the lines are superfluous. (Now that the code is working, I don’t need to log everything to the console. That was just a tool for me to see what was going on as I tried to figure it all out.)

The server code is a little overly complicated since the request body comes in that fancy format rather than a simple string but overall it’s fairly straightforward!

Now to get rid of all the extra bits in both files, so that I only have what I actually need.


  var request = new XMLHttpRequest();
  request.open("POST", '/newDream', true);
  request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); //I don't know how to change to a simpler content type
  request.send("dream=" + dreamInput.value);

I got rid of the extra lines in my client file, but I can’t figure out how to get it to work with a simpler content type. I tried changing it to “text/plain” and only sending dreamInput.value in the request body, but then the server wasn’t finding anything so it was saving a bunch of undefined values to the database.

But really I might as well leave it this way because for my work tracker, I want to be passing multiple values anyway, rather than just a simple string. Why go to the effort to simplify if I’m just going to re-complicate it?


app.post('/newDream', function(request, response){
var dream = request.body.dream;
var sqlStatement = 'INSERT INTO Dreams (dream) VALUES ("' + dream + '")';
db.run(sqlStatement);
response.send("Dream inserted.");
});

Here’s the server code. Not much has changed besides removing the console.log()s.

It works just as well but it’s shorter and I now understand everything — yay!

Leave a comment