Skip to content

Your First SØAD Application: Address Book

This chapter guides you through building a simple web application using the SØAD Framework. We’ll develop an Address Book where users can:

  • View a list of contacts
  • Add a new contact
  • Edit an existing contact
  • Delete a contact

Step 1: Create the Database Table

First, create a table to store contact details in your database.

Table Schema

Create a new table named contact with the following schema:

Column Name Data Type Constraints
id INT NOT NULL, PRIMARY KEY, AUTO_INCREMENT
name VARCHAR(100) NOT NULL
contact_no VARCHAR(20)
email VARCHAR(100)
created_date DATETIME
updated_date DATETIME

Example SQL Script:

CREATE TABLE contact (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100) NOT NULL,
    contact_no VARCHAR(20),
    email VARCHAR(100),
    created_date DATETIME,
    updated_date DATETIME
);

After creating the table, SØAD automatically generates a corresponding model class named Contact.


Step 2: Create the Transaction

Next, create a transaction that manages the contacts. The transaction group is example, and the transaction code is address_book.

Create Transaction

In the SØAD Online IDE, go to the Transaction tab, and create:

  • Group: example
  • Code: address_book
  • Transaction Name: Address Book

This action generates:

example/address_book.py
example/_address_book/address_book.html

Jython Code: address_book.py

from utils import render
from models import Contact
from java.time import LocalDateTime

class Address_book(object):
    def view(self, ctx):
        contacts = Contact.findAll().orderBy("name ASC")
        ctx.output["contacts"] = contacts
        ctx.go_to = render.as_view(ctx, "address_book")

    def save(self, ctx):
        """POST"""
        request = ctx.getRequest()
        id = request.getParameter("id")
        name = request.getParameter("name")
        contact_no = request.getParameter("contact_no")
        email = request.getParameter("email")

        if id:
            contact = Contact.findById(id)
        else:
            contact = Contact()
            contact.set("created_date", LocalDateTime.now())

        contact.set("name", name)
        contact.set("contact_no", contact_no)
        contact.set("email", email)
        contact.set("updated_date", LocalDateTime.now())
        contact.saveIt()

        # Redirect to the view after saving
        ctx.go_to = "/t/example/address_book"  

    def edit(self, ctx):
        request = ctx.getRequest()
        id = request.getParameter("id")
        ctx.output["contact"] = Contact.findById(id)
        self.view(ctx)

    def delete(self, ctx):
        """POST"""
        request = ctx.getRequest()
        id = request.getParameter("id")
        contact = Contact.findById(id)
        if contact:
            contact.delete()

        # Redirect to the view after deletion
        ctx.go_to = "/t/example/address_book"

Tip

  1. Use """POST""" at the beginning of methods like save and delete to indicate that they only accept POST requests. This is particularly useful for handling form submissions securely.

  2. Implement ctx.go_to = "/t/example/address_book" after save or delete actions to redirect users back to the main view. This follows the Post/Redirect/Get (PRG) pattern, preventing unintended form resubmissions when the page is refreshed.

HTML View: _example/address_book.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Address Book</title>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container my-4">
    <h1 class="mb-4">Address Book</h1>

    <form action="{{ctxPath}}/t/example/address_book/save" method="post" class="mb-4">
        <input type="hidden" name="id" value="{{contact.id}}" />

        <div class="mb-3">
            <label class="form-label">Name</label>
            <input type="text" class="form-control" name="name" value="{{contact.name}}" required />
        </div>

        <div class="mb-3">
            <label class="form-label">Contact No</label>
            <input type="text" class="form-control" name="contact_no" value="{{contact.contact_no}}" />
        </div>

        <div class="mb-3">
            <label class="form-label">Email</label>
            <input type="email" class="form-control" name="email" value="{{contact.email}}" />
        </div>

        <button type="submit" class="btn btn-primary">Save Contact</button>
    </form>

    <table class="table table-striped">
        <thead>
            <tr>
                <th>Name</th>
                <th>Contact No</th>
                <th>Email</th>
                <th>Actions</th>
            </tr>
        </thead>
        <tbody>
            {{#each contacts}}
            <tr>
                <td>{{name}}</td>
                <td>{{contact_no}}</td>
                <td>{{email}}</td>
                <td>
                    <a class="btn btn-sm btn-warning" href="{{../ctxPath}}/t/example/address_book/edit?id={{id}}">Edit</a>
                    <form action="{{../ctxPath}}/t/example/address_book/delete" method="post" style="display:inline;">
                        <input type="hidden" name="id" value="{{id}}">
                        <button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Delete this contact?')">Delete</button>
                    </form>
                </td>
            </tr>
            {{/each}}
        </tbody>
    </table>
</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

This HTML leverages Bootstrap for styling the forms and tables to ensure a clean and responsive user interface.

Tip

  • Use {{ctxPath}} to dynamically generate the correct context path for your application.
  • {{../ctxPath}} is used to access the context path from within nested Handlebars templates.

Step 3: Open in Browser

After creating the table and transaction, open the following URL:

https://<your-domain.com>/t/example/address_book

You’ll see:

  • A form to add and edit contacts
  • A responsive table listing contacts
  • Edit and delete buttons

Congratulations — you’ve created your first web application in SØAD!

Next, explore adding validations or integrating additional frontend enhancements.