I have a todo list app that I wrote in angular and I wanted to fade in each todo, when it is created and fade them out before they are deleted. I was only able to get the fade in effect to work, if I apply the effect in the todo-item component, however the fade out effect wouldn't work. I've tried adding the animation to the parent todos component however, that doesn't work for either the fade in or fade out.
todos.component.ts (parent container of todo-items)
animations: [ trigger('fade', [ transition('void => *', [ style({opacity: 0}), animate(1000, style({opacity: 1})) ]), transition('* => void', [ animate(1000, style({opacity: 0})) ]) ])
]
})
export class TodosComponent implements OnInit { todos:Todo[]; constructor(private todoService:TodoService) { } ngOnInit() { this.todoService.getTodos().subscribe(todos=> { this.todos = todos}); } deleteTodo(todo:Todo){ this.todos.splice(this.todos.indexOf(todo), 1); this.todoService.deleteTodo(todo).subscribe(); } addTodo(todo:Todo){ this.todoService.addTodo(todo).subscribe(todo=>{ this.todos.push(todo); }) }
}todos.component.html (parent container of todo-items)
<app-add-todo (addTodo)="addTodo($event)"></app-add-todo>
<app-todo-item
@fade
*ngFor="let todo of todos"
[todo] = "todo"
(deleteTodo)="deleteTodo($event)"
>
</app-todo-item>todo-item.component.ts
export class TodoItemComponent implements OnInit { @Input() todo: Todo; @Output() deleteTodo: EventEmitter<Todo> = new EventEmitter(); setClasses(){ let classes = { todo: true, 'is-complete': this.todo.completed } return classes } onToggle(todo) { todo.completed = !todo.completed; this.todoService.toggleCompleted(todo).subscribe( todo => console.log(todo)); } onDelete(todo){ this.deleteTodo.emit(todo); } constructor(private todoService:TodoService) { } ngOnInit() { }
}todo-item.component.html
<div [ngClass] = "setClasses()"> <p> <input (change)="onToggle(todo)" type="checkbox"/> {{todo.title}} <button (click)="onDelete(todo)">x</button> </p>
</div> 0 3 Answers
For Animations I often use they offer simple animations in css.
To use them, you then only need to add the class to fade int, when clicking delete, you need to set the class for fading out - after the animation finished you really delete the object with a timer.
When deleting you need to dynamically set it to another class something like that can work:
<div [className]="someValue"></div>(from: )
When deleting you also need to create a timer, such that the element is only deleted after the animation finished. Example for a simple timer:
// repeat with the interval of 2 seconds
let timerId = setInterval(() => alert('tick'), 2000);
// after 5 seconds stop
setTimeout(() => { clearInterval(timerId); alert('stop'); }, 5000);Hope it helps!
4I have added one more field to ToDo class, status of perticular todo-item.
Using this status, we can transition the animation state by binding the status property to @fade
Here, I am deleting any random item added in list.
todo-parent.component.ts
@Component({ selector: 'app-todo-parent', templateUrl: './todo-parent.component.html', styleUrls: ['./todo-parent.component.css'], animations: [ trigger('fade', [ transition('void => active', [ // using status here for transition style({ opacity: 0 }), animate(1000, style({ opacity: 1 })) ]), transition('* => void', [ animate(1000, style({ opacity: 0 })) ]) ]) ]
})
export class TodoParentComponent { todoList: {str: string, status: string}[] = []; addItem() { this.todoList.push({str: 'added :' + this.todoList.length, status: 'active'}); } deleteRandom() { const num = Math.ceil(Math.random() * this.todoList.length); this.todoList.splice(num, 1); }
}todo-parent.component.html
<div> <div *ngFor="let todo of todoList" [@fade]="todo.status"> <!-- using status here for transition --> <app-todo-item [todoValue]="todo.str"></app-todo-item> </div>
</div>There is no need to do anything in your todo-item component.
So I figured out the answer to my problem. The fade effect won't apply to component tags. So in my todos.component.html (parent todo-item container) I created a div to wrap my todo-item tag in; and I applied the trigger name to it.
my modified todos.component.html
<app-add-todo (addTodo)="addTodo($event)"></app-add-todo>
<div @fade *ngFor="let todo of todos">
<app-todo-item [todo] = "todo" (deleteTodo)="deleteTodo($event)">
</app-todo-item>
</div> 1