I am using angular 19 and getting error in building project. My app.component.html is
<div>
<div className="navbar">
<nav >
<ul>Todo App</ul>
</nav>
</div>
<div className = "heading" id = "headingBegin">
<div >Put your todo items here</div>
</div>
<div id = "headingForm">
<form action="">
<label for="todotitle">Todo Title</label><br>
<input [(@ngModel)]="task" type="text" id="todoid" value=""><br>
<label for="desc">Todo Description </label><br>
<input type="text" id="descname" name="descname" value=""><br><br>
<input type="button" id="submit-btn" value="Add Todo" (click)="addTask()" >
</form>
@for(task of taskList; track task.id){
<ul class="task-list">
<li> {{task.id}}</li>
<li> {{task.name}}</li>
<li> <button (click)="deleteTask(task.id)">Delete</button> </li>
</ul>
}
</div>
</div>
My app.component.ts is -
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-root',
imports: [RouterOutlet,FormsModule],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent {
title = 'todoapp';
task = "client meet at 12"
// taskList: {id : number, name : string, desc : string, completed: boolean}[] = []
taskList: {id : number, name : string}[] = []
changed(){
}
addTask(){
//let first = array.map(taskList => taskList[0]).filter(val => !isNaN(val));;
//let max = Math.max(...first);
this.taskList.push({id: this.taskList.length+1, name: this.task })
this.task = "";
}
deleteTask(id:number){
this.taskList = this.taskList.filter((item)=>item.id != id)
}
}
and the error I am getting is -
[ERROR] NG5002: The animation trigger output event (@ngModelChange) is missing its phase value name (start or done are currently supported) [plugin angular-compiler]
As you can see I am binding "task" to two way binding with input element using ngModel directive. But don't know where I have gone wrong. Installation was done without error.
I am not sure why you are using @ngModel
for two way binding. Obviously, angular will consider it an animation. You should be using [(ngModel)]
for this purpose. Make sure you import FormsModule
in your component.ts class file. Overall it should look like:
<div>
<div class="navbar">
<nav>
<ul>Todo App</ul>
</nav>
</div>
<div class="heading" id="headingBegin">
<div>Put your todo items here</div>
</div>
<div id="headingForm">
<form action="">
<label for="todotitle">Todo Title</label><br>
<input [(ngModel)]="task" type="text" id="todoid" value=""><br>
<label for="desc">Todo Description </label><br>
<input type="text" id="descname" name="descname" value=""><br><br>
<input type="button" id="submit-btn" value="Add Todo" (click)="addTask()">
</form>
<ul class="task-list" *ngFor="let task of taskList; trackBy: trackByTaskId">
<li>{{ task.id }}</li>
<li>{{ task.name }}</li>
<li><button (click)="deleteTask(task.id)">Delete</button></li>
</ul>
</div>
</div>
Your TS file should look somewhat like:
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-root',
imports: [RouterOutlet, FormsModule],
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
public title: string = 'todoapp';
public task: string = 'client meet at 12';
public taskList: { id: number; name: string }[] = [];
public addTask(): void {
this.taskList.push({ id: this.taskList.length + 1, name: this.task });
this.task = '';
}
public deleteTask(id: number): void {
this.taskList = this.taskList.filter((item) => item.id !== id);
}
public trackByTaskId(index: number, task: { id: number; name: string }): number {
return task.id;
}
}