1 Backend, 5 Frontends — Todo List with Rails, React, Angular, Vue, Svelte, and jQuery

Why are we doing this?

What you’ll need

Building the API

SETUP

Database Setup

default: &default
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
user: test5
password: test5
host: localhost
port: 5432
## Development and test will pull the info from default to make use of your local postgres server
development:
<<: *default
database: todo_backend_development
test:
<<: *default
database: todo_backend_test
## If you plan on deploying to Heroku, the setup below will make sure when you deploy to heroku it will be pointing to your heroku database.
production:
<<: *default
url: <%= ENV['DATABASE_URL'] %>

Creating the Todo Model

Seed the Database

Todo.create({title: "Breakfast", body: "Eat Breakfast"})
Todo.create({title: "Lunch", body: "Eat Lunch"})
Todo.create({title: "Dinner", body: "Eat Dinner"})
p Todo.all

Configuring CORS

# Be sure to restart your server when you modify this file.# Avoid CORS issues when API is called from the frontend app.
# Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests.
# Read more: https://github.com/cyu/rack-corsRails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end

Test the API

{
"title": "Brunch",
"body": "Eating Brunch"
}
{
"title": "Brunch II",
"body": "Eating Brunch II"
}

Complete

React Frontend

Setup

Getting Started

import React from "react"export const App = props => {
////////////////
//STATE
////////////////
// The State we'll save our API Data in
const [todos, setTodos] = React.useState([])
////////////////////////
// FUNCTIONS
////////////////////////
//Our function to grab the latest list of todos
const getTodos = async () => {
//We make a request to our backend server
const response = await fetch("http://localhost:3000/todos")
//Convert the response into a javascript object
const data = await response.json()
//assign the data to our state
setTodos(data)
}
/////////////////////////
// useEffects
/////////////////////////
//useEffect to initially grab todos when page loads
React.useEffect(() => {
getTodos()
}, [])
/////////////////////////
//RETURN JSX
/////////////////////////
return <h1>Hello World</h1>
}

Render the Todos To The Screen

import React from "react"export const App = props => {
////////////////
//STATE
////////////////
// The State we'll save our API Data in
const [todos, setTodos] = React.useState([])
////////////////////////
// FUNCTIONS
////////////////////////
//Our function to grab the latest list of todos
const getTodos = async () => {
//We make a request to our backend server
const response = await fetch("http://localhost:3000/todos")
//Convert the response into a javascript object
const data = await response.json()
//assign the data to our state
setTodos(data)
}
//Function that returns JSX to display todos
const TodosLoaded = () => (
<h2>
{todos.map(todo => (
<div>
<h2>{todo.title}</h2>
<h3>{todo.body}</h3>
</div>
))}
</h2>
)
// Variable with JSX to display if no todos exist
const noTodos = <h1>No Todos</h1>
/////////////////////////
// useEffects
/////////////////////////
//useEffect to initially grab todos when page loads
React.useEffect(() => {
getTodos()
}, [])
/////////////////////////
//RETURN JSX
/////////////////////////
//In the JSX below we run the TodosLoaded function if there is at least one todo or render the contents of noTodos if there isn't any.
return (
<div>
<h1>The Todo App</h1>
{todos.length > 0 ? TodosLoaded() : noTodos}
</div>
)
}

Being able to create a new todo

import React from "react"export const App = props => {
////////////////
//STATE
////////////////
//Blank form object to initialize form and reset it
const blankForm = {
title: "",
body: "",
}
// The State we'll save our API Data in
const [todos, setTodos] = React.useState([])
//State for Our Create Todo Form, initialized with empty strings
const [createForm, setCreateForm] = React.useState(blankForm)
////////////////////////
// FUNCTIONS
////////////////////////
//Our function to grab the latest list of todos
const getTodos = async () => {
//We make a request to our backend server
const response = await fetch("http://localhost:3000/todos")
//Convert the response into a javascript object
const data = await response.json()
//assign the data to our state
setTodos(data)
}
//Function that returns JSX to display todos
const TodosLoaded = () => (
<h2>
{todos.map(todo => (
<div>
<h2>{todo.title}</h2>
<h3>{todo.body}</h3>
</div>
))}
</h2>
)
// Variable with JSX to display if no todos exist
const noTodos = <h1>No Todos</h1>
//Function to update state when people type in create form
const handleCreateChange = event => {
//update the create form state determining the key and value based on the form fields name and value properties since it will be the event target.
setCreateForm({ ...createForm, [event.target.name]: event.target.value })
}
const handleCreate = async event => {
//prevent form from refreshing screen
event.preventDefault()
//make post request to our backend server
const response = await fetch("http://localhost:3000/todos", {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(createForm),
})
//update the list of todos be refetching the list
await getTodos()
//reset form
setCreateForm(blankForm)
}
/////////////////////////
// useEffects
/////////////////////////
//useEffect to initially grab todos when page loads
React.useEffect(() => {
getTodos()
}, [])
/////////////////////////
//RETURN JSX
/////////////////////////
//In the JSX below we run the TodosLoaded function if there is at least one todo or render the contents of noTodos if there isn't any.
return (
<div>
<h1>The Todo App</h1>
<h1>Create a Todo</h1>
<form onSubmit={handleCreate}>
<input
type="text"
name="title"
value={createForm.title}
onChange={handleCreateChange}
/>
<input
type="text"
name="body"
value={createForm.body}
onChange={handleCreateChange}
/>
<input type="submit" value="Create Todo" />
</form>
<h1>Todos</h1>
{todos.length > 0 ? TodosLoaded() : noTodos}
</div>
)
}

Being able to Update a Todo

import React from "react"export const App = props => {
////////////////
//STATE
////////////////
//Blank form object to initialize form and reset it
const blankForm = {
title: "",
body: "",
}
// The State we'll save our API Data in
const [todos, setTodos] = React.useState([])
//State for Our Create Todo Form, initialized with empty strings
const [createForm, setCreateForm] = React.useState(blankForm)
//State for Our Update Todo Form, initialized with empty strings
const [updateForm, setUpdateForm] = React.useState(blankForm)
////////////////////////
// FUNCTIONS
////////////////////////
//Our function to grab the latest list of todos
const getTodos = async () => {
//We make a request to our backend server
const response = await fetch("http://localhost:3000/todos")
//Convert the response into a javascript object
const data = await response.json()
//assign the data to our state
setTodos(data)
}
//Function that returns JSX to display todos
const TodosLoaded = () => (
<>
{todos.map(todo => (
<div>
<h2>{todo.title}</h2>
<h3>{todo.body}</h3>
<button onClick={() => setUpdateForm(todo)}>Edit</button>
</div>
))}
</>
)
// Variable with JSX to display if no todos exist
const noTodos = <h1>No Todos</h1>
//Function to update state when people type in create form
const handleCreateChange = event => {
//update the create form state determining the key and value based on the form fields name and value properties since it will be the event target.
setCreateForm({ ...createForm, [event.target.name]: event.target.value })
}
const handleCreate = async event => {
//prevent form from refreshing screen
event.preventDefault()
//make post request to our backend server
const response = await fetch("http://localhost:3000/todos", {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(createForm),
})
//update the list of todos be refetching the list
await getTodos()
//reset form
setCreateForm(blankForm)
}
//Function to update state when people type in update form
const handleUpdateChange = event => {
//update the update form state determining the key and value based on the form fields name and value properties since it will be the event target.
setUpdateForm({ ...updateForm, [event.target.name]: event.target.value })
}
const handleUpdate = async event => {
//prevent form from refreshing screen
event.preventDefault()
//make put request to our backend server
const response = await fetch(
"http://localhost:3000/todos/" + updateForm.id,
{
method: "put",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(updateForm),
}
)
//update the list of todos be refetching the list
await getTodos()
//reset form
setUpdateForm(blankForm)
}
/////////////////////////
// useEffects
/////////////////////////
//useEffect to initially grab todos when page loads
React.useEffect(() => {
getTodos()
}, [])
/////////////////////////
//RETURN JSX
/////////////////////////
//In the JSX below we run the TodosLoaded function if there is at least one todo or render the contents of noTodos if there isn't any.
return (
<div>
<h1>The Todo App</h1>
<h1>Create a Todo</h1>
<form onSubmit={handleCreate}>
<input
type="text"
name="title"
value={createForm.title}
onChange={handleCreateChange}
/>
<input
type="text"
name="body"
value={createForm.body}
onChange={handleCreateChange}
/>
<input type="submit" value="Create Todo" />
</form>
<h1>Update a Todo</h1>
<form onSubmit={handleUpdate}>
<input
type="text"
name="title"
value={updateForm.title}
onChange={handleUpdateChange}
/>
<input
type="text"
name="body"
value={updateForm.body}
onChange={handleUpdateChange}
/>
<input type="submit" value="Update Todo" />
</form>
<h1>Todos</h1>
{todos.length > 0 ? TodosLoaded() : noTodos}
</div>
)
}

Deleting a Todo

import React from "react"export const App = props => {
////////////////
//STATE
////////////////
//Blank form object to initialize form and reset it
const blankForm = {
title: "",
body: "",
}
// The State we'll save our API Data in
const [todos, setTodos] = React.useState([])
//State for Our Create Todo Form, initialized with empty strings
const [createForm, setCreateForm] = React.useState(blankForm)
//State for Our Update Todo Form, initialized with empty strings
const [updateForm, setUpdateForm] = React.useState(blankForm)
////////////////////////
// FUNCTIONS
////////////////////////
//Our function to grab the latest list of todos
const getTodos = async () => {
//We make a request to our backend server
const response = await fetch("http://localhost:3000/todos")
//Convert the response into a javascript object
const data = await response.json()
//assign the data to our state
setTodos(data)
}
//Function that returns JSX to display todos
const TodosLoaded = () => (
<>
{todos.map(todo => (
<div>
<h2>{todo.title}</h2>
<h3>{todo.body}</h3>
<button onClick={() => setUpdateForm(todo)}>Edit</button>
<button onClick={() => handleDelete(todo)}>Delete</button>
</div>
))}
</>
)
// Variable with JSX to display if no todos exist
const noTodos = <h1>No Todos</h1>
//Function to update state when people type in create form
const handleCreateChange = event => {
//update the create form state determining the key and value based on the form fields name and value properties since it will be the event target.
setCreateForm({ ...createForm, [event.target.name]: event.target.value })
}
const handleCreate = async event => {
//prevent form from refreshing screen
event.preventDefault()
//make post request to our backend server
const response = await fetch("http://localhost:3000/todos", {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(createForm),
})
//update the list of todos be refetching the list
await getTodos()
//reset form
setCreateForm(blankForm)
}
//Function to update state when people type in update form
const handleUpdateChange = event => {
//update the update form state determining the key and value based on the form fields name and value properties since it will be the event target.
setUpdateForm({ ...updateForm, [event.target.name]: event.target.value })
}
const handleUpdate = async event => {
//prevent form from refreshing screen
event.preventDefault()
//make put request to our backend server
const response = await fetch(
"http://localhost:3000/todos/" + updateForm.id,
{
method: "put",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(updateForm),
}
)
//update the list of todos be refetching the list
await getTodos()
//reset form
setUpdateForm(blankForm)
}
const handleDelete = async todo => {
//prevent form from refreshing screen
event.preventDefault()
//make delete request to our backend server
const response = await fetch("http://localhost:3000/todos/" + todo.id, {
method: "delete",
})
//update the list of todos be refetching the list
await getTodos()
}
/////////////////////////
// useEffects
/////////////////////////
//useEffect to initially grab todos when page loads
React.useEffect(() => {
getTodos()
}, [])
/////////////////////////
//RETURN JSX
/////////////////////////
//In the JSX below we run the TodosLoaded function if there is at least one todo or render the contents of noTodos if there isn't any.
return (
<div>
<h1>The Todo App</h1>
<h1>Create a Todo</h1>
<form onSubmit={handleCreate}>
<input
type="text"
name="title"
value={createForm.title}
onChange={handleCreateChange}
/>
<input
type="text"
name="body"
value={createForm.body}
onChange={handleCreateChange}
/>
<input type="submit" value="Create Todo" />
</form>
<h1>Update a Todo</h1>
<form onSubmit={handleUpdate}>
<input
type="text"
name="title"
value={updateForm.title}
onChange={handleUpdateChange}
/>
<input
type="text"
name="body"
value={updateForm.body}
onChange={handleUpdateChange}
/>
<input type="submit" value="Update Todo" />
</form>
<h1>Todos</h1>
{todos.length > 0 ? TodosLoaded() : noTodos}
</div>
)
}

Vue Frontend

Setup

Displaying Todos

<template>
<div></div>
</template>
<script>
export default {
//Name property names the component
name: "App",
// data property has a function that returns an object with app data
data: function () {
return {
todos: [],
baseUrl: "http://localhost:3000/todos",
}
},
//methods is an object of functions
methods: {
getTodos: async function () {
const response = await fetch(this.baseUrl)
const data = await response.json()
this.todos = data
},
},
//create runs after components is initially created, one of many lifecycle functions
created: function () {
this.getTodos()
},
}
</script>
<template>
<div>
<h1>The Todo App</h1>
<hr />
<h3>Todos</h3>
<hr />
<ul>
<li v-for="todo of todos" v-bind:key="todo.id">
**********************
<h4>{{todo.title}}</h4>
<h5>{{todo.body}}</h5>
**********************
</li>
</ul>
</div>
</template>

Creating some todos

<template>
<div>
<h1>The Todo App</h1>
<hr />
<h1>Create a Todo</h1>
<form v-on:submit.prevent="createTodo">
<input type="text" v-model="createTitle" />
<input type="text" v-model="createBody" />
<input type="submit" />
</form>
<hr />
<h3>Todos</h3>
<hr />
<ul>
<li v-for="todo of todos" v-bind:key="todo.id">
**********************
<h4>{{todo.title}}</h4>
<h5>{{todo.body}}</h5>
**********************
</li>
</ul>
</div>
</template>
<script>
export default {
//Name property names the component
name: "App",
// data property has a function that returns an object with app data
data: function () {
return {
todos: [],
baseUrl: "http://localhost:3000/todos",
createTitle: "",
createBody: "",
}
},
//methods is an object of functions
methods: {
getTodos: async function () {
const response = await fetch(this.baseUrl)
const data = await response.json()
this.todos = data
},
createTodo: async function () {
await fetch(this.baseUrl, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: this.createTitle,
body: this.createBody,
}),
})
this.createTitle = ""
this.createBody = ""
this.getTodos()
},
},
//create runs after components is initially created, one of many lifecycle functions
created: function () {
this.getTodos()
},
}
</script>

Editing a Todo

<template>
<div>
<h1>The Todo App</h1>
<hr />
<h1>Create a Todo</h1>
<form v-on:submit.prevent="createTodo">
<input type="text" v-model="createTitle" />
<input type="text" v-model="createBody" />
<input type="submit" />
</form>
<hr />
<h1>Edit a Todo</h1>
<form v-on:submit.prevent="editTodo">
<input type="text" v-model="editTitle" />
<input type="text" v-model="editBody" />
<input type="submit" />
</form>
<hr />
<h3>Todos</h3>
<hr />
<ul>
<li v-for="todo of todos" v-bind:key="todo.id">
**********************
<h4>{{todo.title}}</h4>
<h5>{{todo.body}}</h5>
**********************
<button v-on:click="() => editSelect(todo)">Edit</button>
</li>
</ul>
</div>
</template>
<script>
export default {
//Name property names the component
name: "App",
// data property has a function that returns an object with app data
data: function () {
return {
todos: [],
baseUrl: "http://localhost:3000/todos",
createTitle: "",
createBody: "",
editTitle: "",
editBody: "",
editId: 0,
}
},
//methods is an object of functions
methods: {
getTodos: async function () {
const response = await fetch(this.baseUrl)
const data = await response.json()
this.todos = data
},
createTodo: async function () {
await fetch(this.baseUrl, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: this.createTitle,
body: this.createBody,
}),
})
this.createTitle = ""
this.createBody = ""
this.getTodos()
},
editSelect: function (todo) {
this.editTitle = todo.title
this.editBody = todo.body
this.editId = todo.id
},
editTodo: async function () {
await fetch(this.baseUrl + "/" + this.editId, {
method: "put",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: this.editTitle,
body: this.editBody,
}),
})
this.editTitle = ""
this.editBody = ""
this.editId = 0
this.getTodos()
},
},
//create runs after components is initially created, one of many lifecycle functions
created: function () {
this.getTodos()
},
}
</script>

Deleting a Todo

<template>
<div>
<h1>The Todo App</h1>
<hr />
<h1>Create a Todo</h1>
<form v-on:submit.prevent="createTodo">
<input type="text" v-model="createTitle" />
<input type="text" v-model="createBody" />
<input type="submit" />
</form>
<hr />
<h1>Edit a Todo</h1>
<form v-on:submit.prevent="editTodo">
<input type="text" v-model="editTitle" />
<input type="text" v-model="editBody" />
<input type="submit" />
</form>
<hr />
<h3>Todos</h3>
<hr />
<ul>
<li v-for="todo of todos" v-bind:key="todo.id">
**********************
<h4>{{todo.title}}</h4>
<h5>{{todo.body}}</h5>
**********************
<button v-on:click="() => editSelect(todo)">Edit</button>
<button v-on:click="() => deleteTodo(todo)">Delete</button>
</li>
</ul>
</div>
</template>
<script>
export default {
//Name property names the component
name: "App",
// data property has a function that returns an object with app data
data: function () {
return {
todos: [],
baseUrl: "http://localhost:3000/todos",
createTitle: "",
createBody: "",
editTitle: "",
editBody: "",
editId: 0,
}
},
//methods is an object of functions
methods: {
getTodos: async function () {
const response = await fetch(this.baseUrl)
const data = await response.json()
this.todos = data
},
createTodo: async function () {
await fetch(this.baseUrl, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: this.createTitle,
body: this.createBody,
}),
})
this.createTitle = ""
this.createBody = ""
this.getTodos()
},
editSelect: function (todo) {
this.editTitle = todo.title
this.editBody = todo.body
this.editId = todo.id
},
editTodo: async function () {
await fetch(this.baseUrl + "/" + this.editId, {
method: "put",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: this.editTitle,
body: this.editBody,
}),
})
this.editTitle = ""
this.editBody = ""
this.editId = 0
this.getTodos()
},
deleteTodo: async function (todo) {
await fetch(this.baseUrl + "/" + todo.id, {
method: "delete",
})
this.getTodos()
},
},
//create runs after components is initially created, one of many lifecycle functions
created: function () {
this.getTodos()
},
}
</script>

Angular Frontend

Setup

Displaying Our Todos

import { Component, OnInit } from "@angular/core"@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent implements OnInit {
todos: Array<any> = []
baseUrl: string = "http://localhost:3000/todos"
async getTodos() {
const response = await fetch(this.baseUrl)
const data = await response.json()
this.todos = await data
}
ngOnInit() {
this.getTodos()
}
}
<h1>The Todo App</h1><h2>The Todos</h2>
<ul>
<li *ngFor="let todo of todos">
<h3>{{todo.title}}</h3>
<h4>{{todo.body}}</h4>
</li>
</ul>

Creating Some Todos

import { BrowserModule } from "@angular/platform-browser"
import { NgModule } from "@angular/core"
import { FormsModule } from "@angular/forms"
import { AppRoutingModule } from "./app-routing.module"
import { AppComponent } from "./app.component"
import { HeaderComponent } from "./header/header.component"
import { FooterComponent } from "./footer/footer.component"
import { MainComponent } from "./main/main.component"
@NgModule({
declarations: [AppComponent, HeaderComponent, FooterComponent, MainComponent],
imports: [BrowserModule, AppRoutingModule, FormsModule],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
import { Component, OnInit } from "@angular/core"@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent implements OnInit {
todos: Array<any> = []
baseUrl: string = "http://localhost:3000/todos" //Properties to Bind with Create Form
createTitle: string = ""
createBody: string = ""
//Function to Grab list of todos
async getTodos() {
const response = await fetch(this.baseUrl)
const data = await response.json()
this.todos = await data
}
//takes data from form and creates new todo
async createTodo() {
console.log(this.createTitle, this.createBody)
await fetch(this.baseUrl, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: this.createTitle,
body: this.createBody,
}),
})
//update todo list and reset form
this.getTodos()
this.createTitle = ""
this.createBody = ""
}
//this function runs when the component loads
ngOnInit() {
this.getTodos()
}
}
<h1>The Todo App</h1><h2>Create a Todo</h2>
<form (submit)="createTodo()">
<input type="text" [(ngModel)]="createTitle" name="title" #ctrl="ngModel" />
<input type="text" [(ngModel)]="createBody" name="body" #ctrl="ngModel" />
<input type="submit" value="create Todo" />
</form>
<h2>The Todos</h2>
<ul>
<li *ngFor="let todo of todos">
<h3>{{todo.title}}</h3>
<h4>{{todo.body}}</h4>
</li>
</ul>

Let’s update todos

import { Component, OnInit } from "@angular/core"@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent implements OnInit {
todos: Array<any> = []
baseUrl: string = "http://localhost:3000/todos" //Properties to Bind with Create Form
createTitle: string = ""
createBody: string = ""
//Properties to Bind with Create Form
editTitle: string = ""
editBody: string = ""
editId: number = 0
//Function to Grab list of todos
async getTodos() {
const response = await fetch(this.baseUrl)
const data = await response.json()
this.todos = await data
}
//takes data from form and creates new todo
async createTodo() {
await fetch(this.baseUrl, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: this.createTitle,
body: this.createBody,
}),
})
//update todo list and reset form
this.getTodos()
this.createTitle = ""
this.createBody = ""
}
editSelect(todo) {
this.editId = todo.id
this.editTitle = todo.title
this.editBody = todo.body
}
//takes data from form and updates new todo
async updateTodo() {
await fetch(this.baseUrl + "/" + this.editId, {
method: "put",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: this.editTitle,
body: this.editBody,
}),
})
//update todo list and reset form
this.getTodos()
this.editTitle = ""
this.editBody = ""
this.editId = 0
}
//this function runs when the component loads
ngOnInit() {
this.getTodos()
}
}
<h1>The Todo App</h1>
<hr />
<h2>Create a Todo</h2>
<form (submit)="createTodo()">
<input type="text" [(ngModel)]="createTitle" name="title" #ctrl="ngModel" />
<input type="text" [(ngModel)]="createBody" name="body" #ctrl="ngModel" />
<input type="submit" value="create Todo" />
</form>
<hr />
<h2>Edit a Todo</h2>
<form (submit)="updateTodo()">
<input type="text" [(ngModel)]="editTitle" name="title" #ctrl="ngModel" />
<input type="text" [(ngModel)]="editBody" name="body" #ctrl="ngModel" />
<input type="submit" value="Edit Todo" />
</form>
<hr />
<h2>The Todos</h2>
<ul>
<li *ngFor="let todo of todos">
<h3>{{ todo.title }}</h3>
<h4>{{ todo.body }}</h4>
<button (click)="editSelect(todo)">Edit</button>
</li>
</ul>

Delete a Todo

import { Component, OnInit } from "@angular/core"@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent implements OnInit {
todos: Array<any> = []
baseUrl: string = "http://localhost:3000/todos" //Properties to Bind with Create Form
createTitle: string = ""
createBody: string = ""
//Properties to Bind with Create Form
editTitle: string = ""
editBody: string = ""
editId: number = 0
//Function to Grab list of todos
async getTodos() {
const response = await fetch(this.baseUrl)
const data = await response.json()
this.todos = await data
}
//takes data from form and creates new todo
async createTodo() {
await fetch(this.baseUrl, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: this.createTitle,
body: this.createBody,
}),
})
//update todo list and reset form
this.getTodos()
this.createTitle = ""
this.createBody = ""
}
editSelect(todo) {
this.editId = todo.id
this.editTitle = todo.title
this.editBody = todo.body
}
//takes data from form and updates new todo
async updateTodo() {
await fetch(this.baseUrl + "/" + this.editId, {
method: "put",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: this.editTitle,
body: this.editBody,
}),
})
//update todo list and reset form
this.getTodos()
this.editTitle = ""
this.editBody = ""
this.editId = 0
}
async deleteTodo(todo) {
await fetch(this.baseUrl + "/" + todo.id, {
method: "delete",
})
//update list of todos
this.getTodos()
}
//this function runs when the component loads
ngOnInit() {
this.getTodos()
}
}
<h1>The Todo App</h1>
<hr />
<h2>Create a Todo</h2>
<form (submit)="createTodo()">
<input type="text" [(ngModel)]="createTitle" name="title" #ctrl="ngModel" />
<input type="text" [(ngModel)]="createBody" name="body" #ctrl="ngModel" />
<input type="submit" value="create Todo" />
</form>
<hr />
<h2>Edit a Todo</h2>
<form (submit)="updateTodo()">
<input type="text" [(ngModel)]="editTitle" name="title" #ctrl="ngModel" />
<input type="text" [(ngModel)]="editBody" name="body" #ctrl="ngModel" />
<input type="submit" value="Edit Todo" />
</form>
<hr />
<h2>The Todos</h2>
<ul>
<li *ngFor="let todo of todos">
<h3>{{ todo.title }}</h3>
<h4>{{ todo.body }}</h4>
<button (click)="editSelect(todo)">Edit</button>
<button (click)="deleteTodo(todo)">Delete</button>
</li>
</ul>

Svelte Frontend

Setup

Displaying Our Todos

<script>
import { onMount } from "svelte"
//Variable to hold todos
let todos = []
//base URL
const baseURL = "http://localhost:3000/todos"
//Method to pull data
const getTodos = async () => {
const response = await fetch(baseURL)
const data = await response.json()
todos = await data
}
onMount(() => {
getTodos()
})
</script>
<main>
<h1>The Todo App</h1>
{#each todos as todo}
<div>
<h2>{todo.title}</h2>
<h3>{todo.body}</h3>
</div>
{/each}
</main>
<style></style>

Creating a todo

<script>
import { onMount } from "svelte"
//Variable to hold todos
let todos = []
//base URL
const baseURL = "http://localhost:3000/todos"
//Method to pull data
const getTodos = async () => {
const response = await fetch(baseURL)
const data = await response.json()
todos = await data
}
//Runs when component loads
onMount(() => {
getTodos()
})
//properties for create form
let createTitle
let createBody
//create function for form submission
const createTodo = async event => {
event.preventDefault()
await fetch(baseURL, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: createTitle,
body: createBody,
}),
})
//refetch todos
getTodos()
//reset form
createTitle = ""
createBody = ""
}
</script>
<main>
<h1>The Todo App</h1>
<hr />
<h2>Create a Todo</h2>
<form on:submit="{createTodo}">
<input type="text" bind:value="{createTitle}" />
<input type="text" bind:value="{createBody}" />
<input type="submit" value="Create Todo" />
</form>
<hr />
<h2>The Todos</h2>
{#each todos as todo}
<div>
<h2>{todo.title}</h2>
<h3>{todo.body}</h3>
</div>
{/each}
</main>
<style></style>

Update a Todo

<script>
import {onMount} from 'svelte'
//Variable to hold todos
let todos = []
//base URL
const baseURL = "http://localhost:3000/todos"
//Method to pull data
const getTodos = async () => {
const response = await fetch(baseURL)
const data = await response.json()
todos = await data
}
//Runs when component loads
onMount(()=>{
getTodos()
})
//properties for create form
let createTitle;
let createBody;
//create function for form submission
const createTodo = async (event) => {
event.preventDefault()
await fetch(baseURL, {
method: "post",
headers: {
"Content-Type":"application/json"
},
body: JSON.stringify({
title: createTitle,
body: createBody
})
})
//refetch todos
getTodos()
//reset form
createTitle = ""
createBody = ""
}
//properties for edit form
let editTitle;
let editBody;
let editId
//create function for form submission
const updateTodo = async (event) => {
event.preventDefault()
await fetch(baseURL + "/" + editId, {
method: "put",
headers: {
"Content-Type":"application/json"
},
body: JSON.stringify({
title: editTitle,
body: editBody
})
})
//refetch todos
getTodos()
//reset form
editTitle = ""
editBody = ""
editId = 0
}
const editSelect = (todo) => {
editTitle = todo.title
editBody = todo.body
editId = todo.id
}
</script>
<main><h1>The Todo App</h1>
<hr>
<h2>Create a Todo</h2>
<form on:submit={createTodo}>
<input type="text" bind:value={createTitle}/>
<input type="text" bind:value={createBody}/>
<input type="submit" value="Create Todo"/>
</form>
<hr>
<h2>Edit a Todo</h2>
<form on:submit={updateTodo}>
<input type="text" bind:value={editTitle}/>
<input type="text" bind:value={editBody}/>
<input type="submit" value="Update Todo"/>
</form>
<hr>
<h2>The Todos</h2>
{#each todos as todo}
<div>
<h2>{todo.title}</h2>
<h3>{todo.body}</h3>
<button on:click={(e) => editSelect(todo)}>Edit</button>
</div>
{/each}
</main>
<style>
</style>

Delete a Todo

<script>
import {onMount} from 'svelte'
//Variable to hold todos
let todos = []
//base URL
const baseURL = "http://localhost:3000/todos"
//Method to pull data
const getTodos = async () => {
const response = await fetch(baseURL)
const data = await response.json()
todos = await data
}
//Runs when component loads
onMount(()=>{
getTodos()
})
//properties for create form
let createTitle;
let createBody;
//create function for form submission
const createTodo = async (event) => {
event.preventDefault()
await fetch(baseURL, {
method: "post",
headers: {
"Content-Type":"application/json"
},
body: JSON.stringify({
title: createTitle,
body: createBody
})
})
//refetch todos
getTodos()
//reset form
createTitle = ""
createBody = ""
}
//properties for edit form
let editTitle;
let editBody;
let editId
//create function for form submission
const updateTodo = async (event) => {
event.preventDefault()
await fetch(baseURL + "/" + editId, {
method: "put",
headers: {
"Content-Type":"application/json"
},
body: JSON.stringify({
title: editTitle,
body: editBody
})
})
//refetch todos
getTodos()
//reset form
editTitle = ""
editBody = ""
editId = 0
}
const editSelect = (todo) => {
editTitle = todo.title
editBody = todo.body
editId = todo.id
}
const deleteTodo = async (todo) => {
event.preventDefault()
await fetch(baseURL + "/" + todo.id, {
method: "delete",
})
//refetch todos
getTodos()
}
</script>
<main><h1>The Todo App</h1>
<hr>
<h2>Create a Todo</h2>
<form on:submit={createTodo}>
<input type="text" bind:value={createTitle}/>
<input type="text" bind:value={createBody}/>
<input type="submit" value="Create Todo"/>
</form>
<hr>
<h2>Edit a Todo</h2>
<form on:submit={updateTodo}>
<input type="text" bind:value={editTitle}/>
<input type="text" bind:value={editBody}/>
<input type="submit" value="Update Todo"/>
</form>
<hr>
<h2>The Todos</h2>
{#each todos as todo}
<div>
<h2>{todo.title}</h2>
<h3>{todo.body}</h3>
<button on:click={(e) => editSelect(todo)}>Edit</button>
<button on:click={(e) => deleteTodo(todo)}>Delete</button>
</div>
{/each}
</main>
<style>
</style>

jQuery Frontend

Setup

Displaying Todos

import $ from "jquery"
import _ from "lodash"
//Adding the initial HTML to the body
$("body").append(`
<h1>The Todo App</h1>
<hr>
<h2>The Todos</h2>
<ul id="todolist">
</ul>
`)
//The UL for the Todo List
const $todoList = $("#todolist")
const baseURL = "http://localhost:3000/todos"//function to get todos
const fetchTodos = async () => {
const response = await fetch(baseURL)
const data = await response.json()
//return promise of data
return data
}
//render todos to DOM
const renderTodos = async () => {
const todos = await fetchTodos()
todos.forEach(todo => {
const $li = $("<li>")
$li.html(`
<h3>${todo.title}</h3>
<h4>${todo.body}</h4>
`)
$todoList.append($li)
})
}
// Initial Fetch of Todos
renderTodos()

Creating a Todo

import $ from "jquery";
import _ from "lodash";
//Adding the initial HTML to the body
$("body").append(`
<h1>The Todo App</h1>
<hr>
<h2>Create a Todo</h2>
<form id="createForm">
<input type="text" name="createTitle"/>
<input type="text" name="createBody"/>
<input type="submit" value="Create Todo">
</form>
<hr>
<h2>The Todos</h2>
<ul id="todolist">
</ul>
`);
//The UL for the Todo List
const $todoList = $("#todolist");
//Create Form Variables
const $createForm = $("#createForm");
const $createTitle = $('input[name="createTitle');
const $createBody = $('input[name="createBody');
const baseURL = "http://localhost:3000/todos";
//function to get todos
const fetchTodos = async () => {
const response = await fetch(baseURL);
const data = await response.json();
//return promise of data
return data;
};
//render todos to DOM
const renderTodos = async () => {
const todos = await fetchTodos();
$todoList.empty();
todos.forEach((todo) => {
const $li = $("<li>");
$li.html(`
<h3>${todo.title}</h3>
<h4>${todo.body}</h4>
`);
$todoList.append($li);
});
};
//Function to Create a to do
const createTodo = async (event) => {
event.preventDefault();
await fetch(baseURL, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: $createTitle.val(),
body: $createBody.val(),
}),
});
renderTodos();
$createTitle.val("");
$createBody.val("");
};
//Add Event Listener to Form
$createForm.on("submit", createTodo);
// Initial Fetch of Todos
renderTodos();

Update a Todo

import $ from "jquery";
import _ from "lodash";
//Adding the initial HTML to the body
$("body").append(`
<h1>The Todo App</h1>
<hr>
<h2>Create a Todo</h2>
<form id="createForm">
<input type="text" name="createTitle"/>
<input type="text" name="createBody"/>
<input type="submit" value="Create Todo">
</form>
<hr>
<form id="editForm">
<input type="text" name="editTitle"/>
<input type="text" name="editBody"/>
<input type="submit" value="Update Todo">
</form>
<hr>
<h2>The Todos</h2>
<ul id="todolist">
</ul>
`);
//The UL for the Todo List
const $todoList = $("#todolist");
//Create Form Variables
const $createForm = $("#createForm");
const $createTitle = $('input[name="createTitle"]');
const $createBody = $('input[name="createBody"]');
//Create Form Variables
const $editForm = $("#editForm");
const $editTitle = $('input[name="editTitle"]');
const $editBody = $('input[name="editBody"]');
let editId = 0
//API URL
const baseURL = "http://localhost:3000/todos";
//function to get todos
const fetchTodos = async () => {
const response = await fetch(baseURL);
const data = await response.json();
//return promise of data
return data;
};
//render todos to DOM
const renderTodos = async () => {
const todos = await fetchTodos();
$todoList.empty();
todos.forEach((todo) => {
const $li = $("<li>");
$li.html(`
<h3>${todo.title}</h3>
<h4>${todo.body}</h4>
<button id="${todo.id}editbutton">Edit</button>
`);
$todoList.append($li); $(`#${todo.id}editbutton`).on('click', () => {
$editTitle.val(todo.title)
$editBody.val(todo.body)
editId = todo.id
})
});
};
//Function to Create a to do
const createTodo = async (event) => {
event.preventDefault();
await fetch(baseURL, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: $createTitle.val(),
body: $createBody.val(),
}),
});
renderTodos();
$createTitle.val("");
$createBody.val("");
};
//Function to update a to do
const updateTodo = async (event) => {
event.preventDefault();
await fetch(baseURL + "/" + editId, {
method: "put",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: $editTitle.val(),
body: $editBody.val(),
}),
});
renderTodos();
$editTitle.val("");
$editBody.val("");
};
//Add Event Listener to Form
$createForm.on("submit", createTodo);
//Add Event Listener to Form
$editForm.on("submit", updateTodo);
// Initial Fetch of Todos
renderTodos();11

Delete Todos

import $ from "jquery";
import _ from "lodash";
//Adding the initial HTML to the body
$("body").append(`
<h1>The Todo App</h1>
<hr>
<h2>Create a Todo</h2>
<form id="createForm">
<input type="text" name="createTitle"/>
<input type="text" name="createBody"/>
<input type="submit" value="Create Todo">
</form>
<hr>
<form id="editForm">
<input type="text" name="editTitle"/>
<input type="text" name="editBody"/>
<input type="submit" value="Update Todo">
</form>
<hr>
<h2>The Todos</h2>
<ul id="todolist">
</ul>
`);
//The UL for the Todo List
const $todoList = $("#todolist");
//Create Form Variables
const $createForm = $("#createForm");
const $createTitle = $('input[name="createTitle"]');
const $createBody = $('input[name="createBody"]');
//Create Form Variables
const $editForm = $("#editForm");
const $editTitle = $('input[name="editTitle"]');
const $editBody = $('input[name="editBody"]');
let editId = 0
//API URL
const baseURL = "http://localhost:3000/todos";
//function to get todos
const fetchTodos = async () => {
const response = await fetch(baseURL);
const data = await response.json();
//return promise of data
return data;
};
//render todos to DOM
const renderTodos = async () => {
const todos = await fetchTodos();
$todoList.empty();
todos.forEach((todo) => {
const $li = $("<li>");
$li.html(`
<h3>${todo.title}</h3>
<h4>${todo.body}</h4>
<button id="${todo.id}editbutton">Edit</button>
<button id="${todo.id}deletebutton">Delete</button>
`);
$todoList.append($li); //add function to edit button
$(`#${todo.id}editbutton`).on('click', () => {
$editTitle.val(todo.title)
$editBody.val(todo.body)
editId = todo.id
})
//add function to delete button
$(`#${todo.id}deletebutton`).on('click', async () => {
await fetch(baseURL + "/" + todo.id, {
method: "delete"
})
renderTodos()
})
});
};
//Function to Create a to do
const createTodo = async (event) => {
event.preventDefault();
await fetch(baseURL, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: $createTitle.val(),
body: $createBody.val(),
}),
});
renderTodos();
$createTitle.val("");
$createBody.val("");
};
//Function to update a to do
const updateTodo = async (event) => {
event.preventDefault();
await fetch(baseURL + "/" + editId, {
method: "put",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: $editTitle.val(),
body: $editBody.val(),
}),
});
renderTodos();
$editTitle.val("");
$editBody.val("");
};
//Add Event Listener to Form
$createForm.on("submit", createTodo);
//Add Event Listener to Form
$editForm.on("submit", updateTodo);
// Initial Fetch of Todos
renderTodos();

Congrats

Alex Merced is a Full Stack Developer, learn more about his work at AlexMercedCoder.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store