5. Add your first interaction
Let the service create tasks
class TaskService extends Service<TaskService> {
// Remove hardcoded tasks
private _tasks: ITask[];
constructor() {
super();
this._tasks = [];
}
public createTask(): void {
let id = 0;
if (this._tasks.length > 0){
id = Math.max(...this._tasks.map(task => task.id)) + 1;
}
const newTask: ITask = {
id: id,
name: `Task ${id + 1}`,
};
this._tasks.push(newTask);
}
}
Generate the component
npm run generate component components/new-task
# Creates src/app/components/new-task/new-task.component.ts|html|scss
Add the callback
import { Component, html } from '../../../core/index.js';
import { taskService } from '../../services/task/task.service.js';
const templateFn = () => html`__TEMPLATE_PLACEHOLDER__`;
export class NewTaskComponent extends Component {
/* ... */
private _newTask(): void {
taskService.createTask();
}
}
Bind the callback
<div class="new-task">
<button data-event="click:_newTask">New Task</button>
</div>
The build checks the handler name against the component: a typo like click:_newTsk fails the build, pointing at that line of the template.
A little bit of styling
.new-task {
padding: 2rem;
button {
background: #3C3C3A;
color: #FAFAF9;
padding: 1rem 1.5rem;
font-size: 1.2rem;
border-radius: 8px;
&:hover {
background: #2C2C2A;
}
}
}
Use the component in the view
/* ... */
import { NewTaskComponent } from '../../components/new-task/new-task.component.js';
export class TaskCatalogView extends View {
/* ... */
registerChildren(): Nutin.ComponentConfig[] {
return [
{
selector: 'new-task',
factory: (el) => new NewTaskComponent(el),
},
...this.createCatalogComponents({ /* ... */ })
]
}
}
<div class="task-catalog">
<h1>Nutin Todo</h1>
<!-- data-component attribute = "selector" target -->
<div data-component="new-task"></div>
<!-- ... -->
</div>
Make the view aware of task creation
Define an event
// src/app/globals.d.ts
declare namespace Nutin {
interface AppEventMap {
// to keep this lean, we'll reuse the same event for all operations
'task-event': { taskId: number };
}
}
Emit the event
/* ... */
import { AppEventBus } from '../../../core/index.js';
export class TaskService extends Service<TaskService> {
/* ... */
public createTask(): void {
/* ... */
AppEventBus.emit('task-event', { taskId: newTask.id });
}
}
Listen to the event to re-render the view
export class TaskCatalogView extends View {
constructor() {
/* ... */
this.listenToRenderEvents(['task-event']);
}
}