Axino Tutorial: TODO-List

Serge Hulne
Nov 24, 2020 · 6 min read

Coding a dynamic todo-list in pure Typescript (no frameworks).

Introducing the Axino Widget model, Channels and state handling.

Image for post
Image for post

Live demo of the app:

Why Axino Widgets?

Frameworks (such as Vue, React, Angular, Svelte, etc…) can be used to build web apps, but they require a knowledge of CSS, JavaScript, and HTML, thereby imposing more requirements on the developer, mixing imperative and declarative languages, and mixing business logic with the presentation. The Axino widgets lib on the other hand uses Typescript only, a safer way to generate portable JavaScript, which allows the developer to build a web app using only one simple clear, robust, easy to debug language (moreover an imperative and typed language:

Getting started with Axino:

Axino-related concepts introduced in this tutorial:

  • Composition (Widgets: Composing the elementary components into reusable components or Widgets).
  • Modularity (with Typescript modules).
  • State.
  • Channels (Golang-inspired async inter-widgets communication).

Axino TS is a Widget library aimed at building web apps and hybrid apps using pure Typescript (knowledge of HTML, CSS, and JavaScript are a plus, but by no means a requirement for building apps using Axino TS).

Coding a TODO-list with the Axino Lib

Step 1: A frame for the app:

A basic frame for the app consists of an index.html page to hold the app on the web and an app.ts file which holds the code of the app:

The standard index.html file for an Axino app is coded as follows:

It points to the app.ts file:

<script src="app.ts"></script>

In order to display a list of tasks, we need :

  1. A widget which embodies a frame, a task list.
  2. A widget that represents a single task to appear in the tasks list.

In Axino, Widgets are implemented as Typescript classes inheriting from the Widget class. An elementary task can be coded as:

The file taks.ts represents an elementary task, coded as a div (itself in a wrapper div, for purely aesthetic reasons),

// Create inner Div:                           
this.taskDiv = new Div(text);

It is styled so as to be editable (like a textArea, for instance):

this.taskDiv.Attribute("contenteditable", "true");

NB: The styling of the elements is done from Typescript rather than via a CSS, in agreement with the Axino approach, but a CSS can be used instead if the developer so chooses (in that case, the CSS file has to be linked to the app via the index.html page, as illustrated on the 1st example of this article).

A “check button” and a “task delete button” are further provided for the widget:

// CheckButton:                           
this.checkButton = new CheckBox(); this.checkButton.Margin("10px"); this.checkButton.appendTo(this.wrapperDiv);
// Initially checked:

// Delete task button:
this.deleteButton = new Button("-"); this.deleteButton.Margin("10px"); this.deleteButton.appendTo(this.wrapperDiv);

This creates the following element of the app’s interface:

Image for post
Image for post

At startup of the demo app, two dummy tasks are created and inserted into the tasks list:

which results in:

Image for post
Image for post

The Channels objects appearing in the constructors of the Task objects enable the task widgets to communicate asynchronously with the other Widgets which make up the app (in a manner which we will illustrate below).

Step 3: the task list Widget

In a manner similar to the task Widget, the TaskList Widget is coded by extending the Widget Class, and adding the Button components, Div components, and the corresponding event-handling methods which make up the TaskList Widget:

In the examples, above we have illustrated the use of modularity and composition :

  • Composition is the ability to group elementary components (buttons, Div, etc…) into reusable components, such as the Task Widget and the TaskList Widget with a scriptable style and behavior.
  • Modularity is the ability to separate the code of the app into separate .ts modules which are each responsible for a different aspect of the apps (for instance each Widget can if deemed useful be coded into its own file thereby increasing the readability of the code).
  • Further, if deemed useful, the behavior part of the code of a Widget can itself be stored in its own dedicated file.
  • For illustration purposes, in the case of the TaskList Widget, style and behavior of the Widget are stored into one single short file (see example TakList.ts above).
  • Alternatively, in the case of the Task Widget, the behavior of the Widget has been stored in a separate file: the task_action.ts file as an example of “separation of concerns”:

The TaskAction class extends the Tasks class and provides behavior to the elements of the Task Widget.

Step 4: app.ts: the main module of the app: Channels and State.

The global behavior of the app, the handling of the events and data held by the Widgets, and the handling of the resulting global state of the app is managed by the main module of the app, the app.ts module:

Channels are declared as follows:

//=================================================                       // Channels for transmitting events between widgets:                       //==================================================                       const channel_checked = new Channel("check");                       const channel_delete = new Channel("delete");                       const channel_add = new Channel("add");

They are used to listen to specific events occurring in the ancillary Widgets of the app (Task and TasKList) as follows :

The meaning of this code snippet is as follows:

When one clicks on the “delete” button element of a Task Widget, an event and the associated data is send down the delete Channel (TaksAction module), subsequently the channel_delete Channel in the app.ts module receives the corresponding event/data which is handled in the callback provided as an argument to the channel_delete.listen() method of the channel_delete Channel in the app.ts module.

Step 5: Global state of the app

Recap: So far we have seen how to:

  • Build the code of our app in a modular fashion using Typescript modules.
  • Build reusable components using the Widget class of the Axino Lib.
  • Enable async communication to/from the Widgets in our app using Channels (the Channel class).

Where does the State of the app reside?

Since the app.ts module of our app manages all the data/events of all its components/Widgets (via Channels), it is up to the developer to decide which data (which set of variable(s) of the app.ts module) gives an accurate representation of the state of our task list (our TODO list).

In this case, the state of our list of tasks is held in the all_tasks object of the app (a Vector of Task objects).

// State :
let all_tasks = new Vector<TaskAction>();
let checked_tasks = new Vector<TaskAction>(); let todo_tasks = new Vector<TaskAction>();

Therefore, in this particular instance, the Vector of Tasks: all_tasks *is* the state of the app as illustrated below:

Image for post
Image for post

Code of the example:

The complete code of the app is available here:

Other tutorials:

An Idea (by Ingenious Piece)

Everything Begins With An Idea

Serge Hulne

Written by

Author, scientist (Physics PhD), philosophy, Sci-Fi, thrillers, humor, blues and Irish music, green energy, origins of consciousness.

An Idea (by Ingenious Piece)

No Matter What People Tell You, Words And Ideas Can Change The World.

Serge Hulne

Written by

Author, scientist (Physics PhD), philosophy, Sci-Fi, thrillers, humor, blues and Irish music, green energy, origins of consciousness.

An Idea (by Ingenious Piece)

No Matter What People Tell You, Words And Ideas Can Change The World.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

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