My First (REAL) Javascript Single Page Web Application
Published: 2021-04-21 19:17:37

So, if you've read any of my previous blogs you may recall me mentioning that I had some prior experience with Javascript. In fact, I spent some time teaching the fundamentals of Javascript programming to High School students, which is to say I had a robust understanding of syntax, methods, and mechanics but relatively little experience creating functional JavaScript web applications. And I certainly had no experience combining a JavaScript web application with Rails backend API, but such were the requirements of my current project. 

I started, as I frequently do in life, wondering how I could possibly include John Carpenter in this project. If you are unfamiliar with John Carpenter, God forbid, he is an filmmaker and auteur of the highest order, responsible for such classics as Halloween, Escape From New York, The Thing, and Big Trouble in Little China. For a single page web application, I decided that an all-encompassing John Carpenter Message Board was more than appropriate.

Early in the development process I was crestfallen when I could not find a font resembling the opening title of the Thing.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ybs9wuluupss2wk6t69f.jpg)

But I was able to recreate the Halloween title font, which felt like big win:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o6sf4ut3pfw3y30e1nar.PNG)

But on to the actual application. I began by designing my Rails API backend to accommodate two models: a post and a comment that belongs to a post. Makes sense, right? A message board always begins with a post, and obviously we would want our message board posts to allow for comments. We'll return to this backend later.

In terms of the frontend, I envisioned a very simple UI with post and comment forms active on the page and all user input cascading down: 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1mbji2ql3gajyb0x4eby.PNG)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xbgnsb8t6r9xqxj914sm.PNG)

This was a relatively straightforward application, but there were two areas that proved most challenging: rendering messages AND comments correctly, and creating a durable connection between my DOM and backend.

## Rendering Messages and Comments

I created some initial seed data to begin populating my interface and immediately realized: it's a message board! When a user navigates to the message board they're going to expect message and comments to render simultaneously. Rendering the messages through a basic fetch request was simple, but I wanted to create a single fetch requests that could render the messages AND IF there were any comments, render those as well. 

### Step 1: Add a  Serializer to my Backend

I knew the first stage of this process would be to add a serializer so that comments would appear with my posts.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ppippusj0z3sojmap3ds.PNG)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ir0beu0pz12s70m09xyj.PNG)

Creating my PostSerializer and implementing it in my Post controller successfully created the API output I wanted: 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ykxnkx8qgkzfku1qiwry.PNG)

### Step 3: Add Conditional Logic to My Initial Fetch

Now the only thing to do was add conditional logic to my initial fetchMessages() function that runs when the page is loaded. In essence, if the data returned from the fetch contains comments, they need to be rendered. The entire function ultimately looked like this: 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w40mny1nyjqrtvnmww4h.PNG)

## Rendering Connections Between My DOM and My Backend

The only other thing that really threw me was how to sustain identifying connections between my DOM elements and my backend resources. In a Ruby on Rails application utilizing ActiveRecord, any new database item is saved with an id and possibly a foreign key establishing a relationship to another resource, and that id is usually available through params or some other feature. I can use that to locate the resource and interact with it. But with a Javascript application interacting with a backend Rails API those features aren't inherently present.

I chose to deal with this at the moment the element is rendered to the DOM. For instance, when a user fills out the form to add a new message, a post fetch request is made and the post is added to the backend. When the data is returned, new Javascript Post objects are created with an id, title, content, and created_at date. Those objects are then acted upon with the renderMessage() method. When each message is rendered it is rendered in a div with an id of "message-id#" (example: message-1, message-2). I did the same thing when comments were rendered so that the id of the backend resource was preserved.

The result at the end of the day: a message board where people can discuss everything about their favorite horror director John Carpenter.