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) 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:
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). 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:
//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;
}
});
Top comments (0)