Cardable: Basic Kanban Board made with Javascript and Rails
Tags: javascript, rails, es6
Published: 2021-08-02 02:52:37

Today I'm going to talk about Cardable, my Javascript project for Phase 4 of Flatiron School's Software Engineering Program. Cardable is a basic kanban board (similar to [Trello](https://trello.com/)) single-page application built using Javascript for the frontend and Rails API for the backend. The frontend is styled using a node-sass installation of Bulma CSS.

## Backend

### Models
Cardable has only two models, Columns and Cards, with a basic association whereby a Column has-many Cards. I wanted a very simple application where a user could create and move cards around columns, all handled by Javascript, so the models don't have any additional methods.

### Controllers

My columns controller contains only the `#index` method:
```ruby
  def index
    columns = Column.all
    render json: columns, include: [:cards]
  end
```
I chose not to implement adding/removing/editing columns, so I only needed to be able to get all columns to display them. I chose to render JSON with associated Cards; this way, when initially loading the webpage, the application only needs to make a single GET request to /columns in order to build all the Column and Card instances.

My cards controller had basic implementations of `#index`, `#create`, `#update`, and `#destroy` methods.

## Frontend

### Classes
My Column and Card classes were structured similarly with the following characteristics:
* Constructor methods that take in a JSON response from a GET fetch request and instantiate a Javascript Object
* A static method for retrieving all instances of the class
* Methods that essentially correspond to each method in the corresponding Rails controller. Both Column and Card have a method that build HTML structure for the model and render the instances to the page (using the GET response data from /columns). Additionally, Card has methods for POSTing, PATCHing, and DELETEing data, allowing the user to create new cards in a column, move cards to a different column, and delete cards.

I added a separate method to Column to create a form that would be added to each column and used to create new cards.

### Running the Application

My `index.js` file is fairly simple, containing a fetch request to /columns that first instantiates Column and Card objects and then renders them to the page. It also has several methods for handling dragging-and-dropping (adapted from the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API)). The important thing I needed to add to the drag-and-drop functionality was to trigger a PATCH request when a Card gets dropped so the Column it belongs to can get updated in the database when moving to a different column. This was handled accordingly:

```javascript
//index.js

const cardToUpdate = Card.all().find(card => card.id == movingCard.getAttribute('id').slice(-1)); // find the Card instance with the id that matches the id of the element being dropped
cardToUpdate.moveColumn(el);

//card.js
moveColumn(el) { // el is the div the card is being dropped onto and is passed in from the drop method in index.js
  const columnId = el.id.slice(-1); // gets the id of the column the card is being moved to
  const cardId = this.id; // gets the id of the card
  const data = {
    id: cardId,
    column_id: columnId
  }
  fetch('http://localhost:3000/cards/' + this.id, {
    method: "PATCH",
    headers: {
      "Content-Type": "application/json",
      Accept: "application/json"
    },
    body: JSON.stringify(data) // sends the card id and column id to the API to get updated in the database
  })
  .then(response => response.json())
  .then(card => {
    if (card) { // if we get a response back, update the column_id of our Javascript Card instance
    this.column_id = columnId;
    }
  });
```