//GET API. Contains the logic to fetch existing to-do items.
function getTodos() {
$.ajax({
url: /server/to_do_list_function/all?page=${page}&perPage=200, //Ensure that ’to_do_list_function’ is the package name of your function.
success: function (data) {
const {
data: { todoItems, hasMore }
} = data;
function renderTodo() {
if (!todoItems.length) {
$(’#tasks’).html(
<div class='p-20 dF jC-center'> <p class='text-info text-16'> No tasks available, Create a new task. </p> </div>
);
} else {
let html = ‘’;
$.ajax({
method: ‘POST’,
contentType: ‘application/json’,
url: ‘/server/to_do_list_function/add’, //Ensure that ’to_do_list_function’ is the package name of your function.
data: JSON.stringify({ notes }),
success: function (data) {
const {
data: { todoItem }
} = data;
Note: The Python function package name to_do_list_function has been added in the code for main.js in the lines 13 and 182. If you have provided a different package name, ensure you replace accordingly.
The client directory is now configured.
Let’s quickly go over the working of the function and the client code:
POST Operation
When the user enters a to-do list item in the app and saves it, the submit event associated with the Create Task button triggers an Ajax call to the POST API.
The main.js in the client handles the Ajax operation and the URL, and it calls the POST API defined in the main.py function file.
The POST API defined in main.py inserts the data as a record in the TodoItems table in the Data Store. The list item is inserted as the value of the Notes column.
After a record insertion is done, the response (new task) will be added to the to-do list.
GET Operation
The reload event triggers an Ajax call to the GET API. The URL and the Ajax operation are handled in main.js.
The GET API defined in main.py obtains all the records from the Data Store by executing a ZCQL query. The ZCQL query contains the fetch operation along with the start-limit and the end-limit of the number of records that can be fetched.
The response containing the records (tasks) will be added to the existing to-do list.
DELETE Operation
The main.js handles the Ajax call to the DELETE API. When the user hovers on a particular task, and clicks on the appearing delete-bin icon in the client app, the DELETE API is triggered.
The DELETE API defined in main.py then executes the delete operation for the record in the TodoItems table matching the ROWID and sends the response back to the client.
The main.js removes the respective record (deleted task) from the to-do list and displays the updated to-do list in the client app upon a successful delete operation.
Configure an Angular web app
The Angular web client directory contains the following files:
The root directory of the client contains a
client-package.jsonfile, which is a configuration file defining the name, version, and default home page of the client component.
Native Angular files such as angular.json,
karma.conf.js,
tsconfig.app.json,
tsconfig.json,
tsconfig.spec.json files, and the
dist directory.
The src folder contains the following files and directories as per the
default project structure of the Angular app:
Native Angular files such as favicon.ico, main.ts, polyfills.ts, and test.ts files along with the assets, and environment directories.
index.html: The default entry point of the to-do list application.
style.css: Contains all the style elements of the to-do list application.
The files present in the src/app/ directory are:
Native Angular files such as app.component.css and
app.component.spec.ts.
app.component.html: Contains the HTML component of each event generated by the user.
app.component.ts: Contains the logic of the to-do list application.
app.module.ts: Contains the meta of all the components used in building the to-do list application.
We will be coding the index.html, style.css, app.component.html, app.component.ts, and the app.module.ts files.
Create a Task Component
You must create a task component that contains the logic associated with each to-do task the end-
user enters. Execute the following command in the src/app/ directory to
create the task component:
copy
$
ng generate component task
This will create a folder named task that contains:
The task.component.css and the task.component.spec.ts files native to Angular.
task.component.html: Contains the HTML component of each to-do task
entered by the user.
task.component.ts: Contains the logic of each to-do task entered by the
user.
We will be coding the task.component.html and task.component.ts files as
well.
Install the Axios Package
We will also need the axios package to create a request from client to server.
To install axios, navigate to the client directory (client/) and execute the following command:
copy
$
npm install axios
This will install the axios module and save the dependencies.
You can now begin adding code in your files.
Note: Please go through the code given in this section to ensure you fully understand
it.
Copy the code given below and paste it in index.html and style.css files located in client directory (client/src/) respectively using an IDE and save the file.
Copy the code given below and paste it in app.component.html, app.component.ts, app.module.ts files respectively located in the client directory (client/src/app/) using an IDE and save the file.
import axios from ‘axios’;
import { Component, OnInit } from ‘@angular/core’;
@Component({
selector: ‘app-root’,
templateUrl: ‘./app.component.html’,
})
export class AppComponent implements OnInit {
notes: string;
page: number;
hasMore: boolean;
todoItems: Array<{ id: string; notes: string; }>;
submitting: boolean;
fetchState: ‘init’ | ‘fetched’ | ’loading’;
constructor() {
this.notes = ‘’;
this.hasMore = false;
this.page = 1;
this.todoItems = [];
this.submitting = false;
this.fetchState = ‘init’;
}
//GET API. The existing to-do items from the Datastore is being fetched.
getTodos = (): void => {
axios
.get(’/server/to_do_list_function/all’, { //Ensure that ’to_do_list_function’ is the package name of your function.
params: {
page: this.page,
perPage: 200,
},
})
.then((response) => {
const {
data: { todoItems, hasMore },
} = response.data;
if (this.page === 1) {
this.todoItems = todoItems as Array<{ id: string; notes: string }>;
} else {
this.todoItems = [
…new Map(
this.todoItems.concat(todoItems).map((item) => [item.id, item])
).values(),
];
}
this.hasMore = hasMore;
this.fetchState = ‘fetched’;
})
.catch((err) => {
console.error(err.response.data);
});
};
//POST API. A new to-do item is being created.
createTodo = (): void => {
this.submitting = true;
axios
.post(/server/to_do_list_function/add, { //Ensure that ’to_do_list_function’ is the package name of your
function.
notes: this.notes,
})
.then((response) => {
const {
data: { todoItem },
} = response.data;
this.notes = ‘’;
this.todoItems = [{ …todoItem }].concat(this.todoItems);
})
.catch((err) => {
console.error(err.response.data);
})
.finally(() => {
this.submitting = false;
});
};
removeTodo = (id: string): void => {
this.todoItems = this.todoItems.filter((obj) => obj.id !== id);
};
changePage = (): void => {
if (this.hasMore) {
this.page += 1;
this.fetchState = ’loading’;
this.getTodos();
}
};
ngOnInit() {
this.fetchState = ‘init’;
this.getTodos();
}
}
View more
Note: The Python function package’s name to_do_list_function has been added in the code for app.component.ts in the lines 33, and 65. If you have provided a different package name, ensure you replace accordingly.
app.module.ts
copy
import { NgModule } from ‘@angular/core’;
import { BrowserModule } from ‘@angular/platform-browser’;
import { FormsModule } from ‘@angular/forms’;
import { AppComponent } from ‘./app.component’;
import { TaskComponent } from ‘./task/task.component’;
Copy the code given below and paste it in task.component.html and task.component.ts, files located in the client directory (client/src/app/task/) using an IDE and save the file.
this.options = false;
this.deleting = false;
this.removeTodo = new EventEmitter();
this.changePage = new EventEmitter();
}
mouseEnter = () => {
this.options = true;
};
mouseLeave = () => {
this.options = false;
};
deleteTodo = () => {
this.deleting = true;
//DELETE API. The call to delete the to-do item from the data store occurs here.
axios
.delete(/server/to_do_list_function/${this.id}) //Ensure that ’to_do_list_function’ is the package name of your function.
.then((response) => {
const {
data: {
todoItem: { id },
},
} = response.data;
this.removeTodo.emit(id);
})
.catch((err) => {
console.log(err.response.data);
})
.finally(() => {
this.deleting = false;
});
};
ngAfterViewInit() {
if (this.isLast && this.element) {
this.observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
this.changePage.emit();
}
});
this.observer.observe(this.element.nativeElement);
}
}
ngOnDestroy() {
if (this.observer) {
this.observer.disconnect();
}
}
}
View more
Note: The Python function package’s name to_do_list_function has been added in the code for task.component.ts in the lines 51. If you have provided a different package name, ensure you replace accordingly.
The client directory is now configured.
Let’s quickly go over the working of the function and the client code:
POST Operation
When the user enters a to-do list item in the app and saves it, the submit event Create Task button triggers an Ajax call to the POST API.
The app.component.ts in the client handles the Ajax operation and the URL, and it calls the POST API defined in the main.py function file.
The POST API defined in main.py inserts the data as a record in the TodoItems table in the Data Store. The list item is inserted as the value of the Notes column.
After a record insertion is done, the response (new task) will be added to the to-do list.
GET Operation
The reload event triggers an Ajax call to the GET API. The URL and the Ajax operation are handled in app.component.ts.
The GET API defined in main.py obtains all the records from the Data Store by executing a ZCQL query. The ZCQL query contains the fetch operation along with the start-limit and the end-limit of the number of records that can be fetched.
The response containing the records (tasks) will be added to the existing to-do list.
DELETE Operation
When the user clicks on a list item in the client app, the DELETE API is triggered.
The task.component.ts handles the Ajax call to the DELETE API. When the user hovers on a particular task, and clicks on the delete-bin icon that appears in the client, the DELETE API is triggered.
The DELETE API defined in main.py then executes the delete operation for the record in the TodoItems table matching the ROWID and sends the response back to the client.
The app.component.ts removes the respective record (deleted task) from the To-Do list and displays the updated list in the client app upon a successful delete operation.
The root directory of the client contains a client-package.json file which is a configuration file defining the name, version, and default home page of the client component.
The app folder contains two subfolders as per the default project structure of a React app:
The public folder is generally used to hold files that can be openly accessed by browsers through public URLs, such as icon files of the web app and index.html.
The src folder contains the application’s source files that will be included in the build folder when we compile the React app.
Native React files such as favicon.ico, logo192.png, manifest.json, logi512.png and robots.txt. These files will not be necessary for rendering the to-do list application.
index.html: The default entry point of the to-do list application.
The files present in the src folder include:
Native React files such as setupTests.js, index.js, reportWebVitals.js, logo.svg, and App.test.js.
App.js: Contains the logic of to-do list.
index.css: Contains the styling elements of the native elements.
App.css: Contains the styling elements of the application.
You will also be creating an additional file helper.css. This file will contain utility classes, that will be responsible for certain minor styling.
We will be coding index.html, App.js, helper.css, index.css, and the App.css files.
Install the Axios Package
We will need the axios package to create a request from client to server.
To install axios, navigate to the client directory (app/) and
execute the following command:
copy
$
npm install axios
This will install the axios module and save the dependencies.
Note: Please go through the code given in this section to ensure you fully understand it.
Copy the code given below and paste it in index.html located in client directory (app/public/) using an IDE and save the file.
Copy the respective code given below and paste it in App.js, index.css, App.css and helper.css respectively located in client directory (app/src/) using an IDE and save the file.
App.js
copy
import ‘./App.css’;
import ‘./helper.css’;
import axios from ‘axios’;
import { forwardRef, useCallback, useEffect, useRef, useState } from ‘react’;
//This segment contains the logic that displays each individual task present in the to-do list
useEffect(() => {
if (fetchState !== ‘fetched’) {
axios
.get(’/server/to_do_list_function/all’, { //Ensure that ’to_do_list_function’ is the package name of your function.
params: { page, perPage: 200 } //The parameters contain the start limit and the end limit of data (tasks) that can be fetched from the data store
})
.then((response) => {
const {
data: { todoItems, hasMore }
} = response.data;
Note: The Python function package’s name to_do_list_function has been added in the code in App.js in the lines 26, 97 and 153. If you have provided a different package name, ensure you replace accordingly.
Let’s quickly go over the working of the function and the client code:
POST Operation
When the user enters a to-do list item in the app and saves it, the submit event associated with the Create Task button triggers an Ajax call to the POST API.
The App.js in the client handles the Ajax operation and the URL, and it calls the POST API defined in the main.py function file.
The POST API defined in main.py inserts the data as a record in the TodoItems table in the Data Store. The list item is inserted as the value of the Notes column.
After a record insertion is done, the response (new task) will be added to the to-do list.
GET Operation
The reload event triggers an Ajax call to the GET API. The URL and the Ajax operation are handled in App.js.
The GET API defined in main.py obtains all the records from the Data Store by executing a ZCQL query. The ZCQL query contains the fetch operation along with the start-limit and the end-limit of the number of records that can be fetched.
The response containing the records (tasks) will be added to the existing to-do list.
DELETE Operation
The App.js handles the Ajax call to the DELETE API. When the user hovers on a particular task, and clicks on the appearing delete-bin icon in the client app, the DELETE API is triggered.
The DELETE API defined in main.py then executes the delete operation for the record in the TodoItems table matching the ROWID and sends the response back to the client.
The App.js removes the respective record (deleted task) from the to-do list and displays the updated to-do list in the client app upon a successful delete operation.