Skip to content

Example

Azarattum edited this page Nov 24, 2020 · 4 revisions

This is a browser example.

As a classic example, let's build a to-do app. To start with, we create a note model:

export default class Note {
	public text: string;
	public date: Date;

	public constructor(text: string = "") {
		this.text = text;
		this.date = new Date();
	}
}

Then we make a view for our notes:

views
└── notes
    ├── notes.pug
    ├── notes.scss
    └── notes.view.ts

notes.pug:

.notes
    each note, number in notes
        .note
            .number=+number + 1
            .text=note.text
            .date=new Date(note.date).toTimeString().slice(0,5)
            button(onclick=`ctrl.removeNote(${number})`) X

.controls
    input(type="text" value=text)
    button(onclick="ctrl.createNote()") CREATE

notes.view.ts

import View from "../../../common/view.abstract";
import Template from "./notes.pug";
import "./notes.scss";

export default class Notes extends View(Template) {}

notes.scss:

view-notes {
	display: flex;
	flex-direction: column;
	width: max-content;

	.note {
		display: flex;
		justify-content: space-between;
		width: 100%;

		div {
			margin: 16px;
		}
	}

	.controls {
		display: flex;

		input {
			width: 100%;
		}
	}
}

Finally, let's add a controller to make our app alive!

import { expose } from "../../common/component.interface";
import Controller, { bind, Relation } from "../../common/controller.abstract";
import Note from "../models/note.class";

export default class Editor extends Controller<never>(Relation.Binding) {
	@bind
	private notes: Note[] = [];

	@expose
	public createNote(text?: string): void {
		this.notes.push(new Note(text ?? this.data.text));
		if (text == null) this.data.text = "";
	}

	@expose
	public removeNote(id: number): void {
		this.notes.splice(id, 1);
	}
}

Do not forget to register created components:

app.ts:

import Application from "../common/application.abstract";
import Editor from "./controllers/editor.controller";
import Notes from "./views/notes/notes.view";

export default class App extends Application {
	public constructor() {
		super([Notes, Editor]);
	}

	public async initialize(): Promise<void> {
		await super.initialize();
	}
}

Now we can just add our view to the DOM:

index.pug:

<!DOCTYPE html>
html(lang="en")
    head
        meta(charset="UTF-8")
        meta(name="viewport" content="width=device-width, initial-scale=1.0")
        meta(http-equiv="X-UA-Compatible" content="ie=edge")
        title ToDo List
        style
            include index.css
    body
        view-notes(controller="editor")

We even can add multiple of them and they all will work independently!

    body
        view-notes(controller="editor")
        view-notes(controller="editor")

To test our application we start a webpack dev server:

npm start

Our page should be available on http://localhost:8080/.

To make a production build we run the release script:

npm release

We should get:

dist
├── bundle.js
└── index.html

The files above are published on https://tf-example.surge.sh/. Go on and try running this command in your browser console to test how the exposing works!

editor.createNote("A note!");

This isn't the most beautiful ToDo list, because we wrote only basic layout styles. You might also want to add some input validations (for empty or long string). That is just a simple application to get started. There are lots of cool TheFramework features beyond this example for you to explore!