Entities
Let's start coding the app by defining the Task
entity class.
The Task
entity class will be used:
- As a model class for client-side code
- As a model class for server-side code
- By
remult
to generate API endpoints, API queries, and database commands
The Task
entity class we're creating will have an auto-increment id
field a title
field and a completed
field. The entity's API route ("tasks") will include endpoints for all CRUD
operations.
Define the Model
Create a
shared
folder under thesrc
folder. This folder will contain code shared between frontend and backend.Create a file
Task.ts
in thesrc/shared/
folder, with the following code:
// src/shared/Task.ts
import { Entity, Fields } from "remult"
@Entity("tasks", {
allowApiCrud: true
})
export class Task {
@Fields.autoIncrement()
id = 0
@Fields.string()
title = ""
@Fields.boolean()
completed = false
}
- In the server's
api
module, register theTask
entity with Remult by addingentities: [Task]
to anoptions
object you pass to theremultExpress()
middleware:
// src/server/api.ts
import { remultExpress } from "remult/remult-express"
import { Task } from "../shared/Task"
export const api = remultExpress({
entities: [Task]
})
The @Entity decorator tells Remult this class is an entity class. The decorator accepts a key
argument (used to name the API route and as a default database collection/table name), and an options
argument used to define entity-related properties and operations, discussed in the next sections of this tutorial.
To initially allow all CRUD operations for tasks, we set the option allowApiCrud to true
.
The @Fields.autoIncrement
decorator tells Remult to automatically generate an id using the databases's auto increment capabilities.
The @Fields.string decorator tells Remult the title
property is an entity data field of type String
. This decorator is also used to define field-related properties and operations, discussed in the next sections of this tutorial and the same goes for @Fields.boolean
and the completed
property.
Test the API
Now that the Task
entity is defined, we can start using the REST API to query and add a tasks.
Open a browser with the url: http://localhost:3002/api/tasks, and you'll see that you get an empty array.
Use
curl
toPOST
a new task - Clean car.
curl http://localhost:3002/api/tasks -d "{\"title\": \"Clean car\"}" -H "Content-Type: application/json"
Refresh the browser for the url: http://localhost:3002/api/tasks and see that the array now contains one item.
Use
curl
toPOST
a few more tasks:
curl http://localhost:3002/api/tasks -d "[{\"title\": \"Read a book\"},{\"title\": \"Take a nap\", \"completed\":true },{\"title\": \"Pay bills\"},{\"title\": \"Do laundry\"}]" -H "Content-Type: application/json"
- Note that the
POST
endpoint can accept a singleTask
or an array ofTask
s.
- Refresh the browser again, to see that the tasks were stored in the db.
Wait, where is the backend database?
While remult supports many relational and non-relational databases, in this tutorial we start by storing entity data in a backend JSON file. Notice that a db
folder has been created under the root folder, with a tasks.json
file containing the created tasks.
Display the Task List
Let's start developing the web app by displaying the list of existing tasks in an Angular component.
Create a
Todo
component using Angular's clishng g c todo
Replace the
app.components.html
to use thetodo
component.- html
<!-- src/app/app.component.html --> <app-todo></app-todo>
Add the highlighted code lines to the
TodoComponent
class file:ts// src/app/todo/todo.component.ts import { Component, OnInit } from '@angular/core'; import { remult } from 'remult'; import { Task } from '../../shared/Task'; @Component({ selector: 'app-todo', templateUrl: './todo.component.html', styleUrls: ['./todo.component.css'] }) export class TodoComponent implements OnInit { taskRepo = remult.repo(Task) tasks: Task[] = [] ngOnInit() { this.taskRepo.find().then(items => this.tasks = items) } }
Here's a quick overview of the different parts of the code snippet:
taskRepo
is a Remult Repository object used to fetch and create Task entity objects.tasks
is a Task array.- The
ngOnInit
method calls theRemult repository's find method to fetch tasks from the server, once when the component is loaded.
Replace the contents of
todo.component.html
with the following HTML:html<!-- src/app/todo/todo.component.html --> <h1>todos</h1> <main> <div *ngFor="let task of tasks"> <input type="checkbox" [(ngModel)]="task.completed" /> {{task.title}} </div> </main>
After the browser refreshes, the list of tasks appears.