Todo List App – Lesson 4 – HTML & CSS

Author: Dawid Adach

-

1. Editing the AppComponent Component

When you initialize a new application, Angular CLI automatically generates a main AppComponent component for us:

src/app/app.component.css
src/app/app.component.html
src/app/app.component.spec.ts
src/app/app.component.ts
  1. Open src/app/app.component.html
    <!-- Start your project here-->
    <div style="height: 100vh">
        <div class="flex-center flex-column">
          <h1 class="animated fadeIn mb-4">Material Design for Bootstrap (Angular)</h1>
      
          <h5 class="animated fadeIn mb-3">Thank you for using our product. We're glad you're with us.</h5>
          <h6 class="animated fadeIn mb-3">Start browsing <a href="https://mdbootstrap.com/angular">documentation</a>.</h6>
      
          <p class="animated fadeIn text-muted">MDB Team</p>
        </div>
      </div>
      <!-- /Start your project here-->
    
  2. Replace default MDB placeholder with application logic:
    <div class="container">
      <div class="row mt-5">
        <div class="col-md-12 text-center">
          <h1 class="h1-responsive">MDB Todo App:</h1>
        </div>
      </div>
      <div class="row mt-5 ">
        <div class="col-md-3 offset-md-2 left-column mb-1">
          <ul class="list-group">
            <li *ngFor="let category of categories" class="list-group-item d-flex justify-content-between align-items-center" (click)="onSelect(category)">
              {{category.name}}
              <span class="badge primary-color badge-pill">{{countTodosByCat(category.id)}}</span>
            </li>
            <li class="list-group-item d-flex justify-content-between align-items-center">
              <form>
                <input mdbActive type="text" placeholder="Add new category" id="form1" class="form-control" [(ngModel)]="newCategory.name"
                  (keyup.enter)="addCategory()" name="addCat">
              </form>
              <span class="badge primary-color badge-pill">
                <a class="prefix">
                  <i class="fa fa-plus" aria-hidden="true" (click)="addCategory()"></i>
                </a>
              </span>
            </li>
          </ul>
        </div>
        <div class="col-md-5 list mb-1" *ngIf="selectedCategory; else elseBlock">
          <div class="row px-3 py-3">
            <div class="col-md-12">
              <h4>{{selectedCategory.name}}</h4>
            </div>
          </div>
          <div class="row px-4 mt-3">
            <div class="form-group full-width" *ngIf="todosForCat.length > 0">
              <form class="full-width">
                <div *ngFor="let todo of todosForCat">
                  <input type="checkbox" id="{{todo.id}}" (click)="toggleTodoComplete(todo)" [checked]="todo.complete">
                  <label for="{{todo.id}}" [ngClass]="{'strikethrough' : todo.complete}">{{todo.title}}</label>
                  <button type="button" class="close" aria-label="Close" style="float: right;" (click)="removeTodo(todo)">
                    <span aria-hidden="true" >&times;</span>
                  </button>
                </div>
              </form>
            </div>
          </div>
          <div class="row px-4 mt-1">
            <div class="md-form">
              <form>
                <a class="prefix">
                  <i class="fa fa-plus prefix" (click)="addTodo()"></i>
                </a>
                <input mdbActive type="text" id="form2" class="form-control" [(ngModel)]="newTodo.title" (keyup.enter)="addTodo()" name="addNew">
                <label for="form2">Add new task</label>
              </form>
            </div>
          </div>
        </div>
        <ng-template #elseBlock>
          <div class="col-md-5 test 5 list text-center">
            <h5 class="pt-3">Choose category from menu in the left.</h5>
            <p class="pt-5">You can also create a new category by typing the name and pressing the enter or clicking on the
              <span class="badge primary-color badge-pill">
                <i class="fa fa-plus" aria-hidden="true"></i>
              </span>
              button.
            </p>
          </div>
        </ng-template>
      </div>
    </div>
    

2. Adding logic

  1. Open app.component.ts file which contains main component TS code:
    import { Component } from '@angular/core';
    
    @Component({
      selector: 'mdb-root',
      templateUrl: 'app.component.html',
      styleUrls: ['app.component.css']
    
    })
    
    export class AppComponent {
    }
    
    
  2. Add following logic:
    import { CategoryDataService } from './categories/category-data.service';
    import { Component, OnInit } from '@angular/core';
    import {Todo} from './todos/todo';
    import {TodoDataService} from './todos/todo-data.service';
    import {Category} from './categories/category';
    
    @Component({
      selector: 'mdb-root',
      templateUrl: 'app.component.html',
      styleUrls: ['app.component.css'],
      providers: [TodoDataService, CategoryDataService]
    
    })
    
    export class AppComponent implements OnInit {
    
      newTodo: Todo = new Todo();
      newCategory: Category = new Category();
      selectedCategory: Category;
    
      constructor(private todoDataService: TodoDataService, private categoryDataService: CategoryDataService) {
      }
    
    
      addTodo() {
        this.newTodo.category = this.selectedCategory.id;
        this.todoDataService.addTodo(this.newTodo);
        this.newTodo = new Todo();
        console.log(this.todos);
      }
    
      toggleTodoComplete(todo) {
        this.todoDataService.toggleTodoComplete(todo);
      }
    
      removeTodo(todo) {
        this.todoDataService.deleteTodoById(todo.id);
      }
    
      get todos() {
        return this.todoDataService.getAllTodos();
      }
    
      get todosForCat() {
        return this.todoDataService.getTodoByCategory(this.selectedCategory.id);
      }
    
      countTodosByCat(id: number) {
        return this.todoDataService.getTodoByCategory(id).length;
      }
    
      addCategory() {
        this.categoryDataService.addCategory(this.newCategory);
        this.newCategory = new Category();
      }
    
      removeCategory(category) {
        this.categoryDataService.deleteCategoryById(category.id);
      }
    
      get categories() {
        return this.categoryDataService.getAllCategories();
      }
    
      categoryById(id: number) {
        return this.categoryDataService.getCategoryById(id);
      }
    
      addInitialCategory(category) {
        this.categoryDataService.addCategory(category);
      }
    
      addInitialTodo(todo) {
        this.todoDataService.addTodo(todo);
      }
    
    
      onSelect(category: Category): void {
        this.selectedCategory = category;
      }
    
      ngOnInit() {
        let initCat = new Category();
        initCat = {'name' : 'Today', 'id' : null , };
        this.addInitialCategory(initCat);
        initCat = {'name' : 'Tomorrow', 'id' : null , };
        this.addInitialCategory(initCat);
        initCat = {'name' : 'Work', 'id' : null , };
        this.addInitialCategory(initCat);
        initCat = {'name' : 'Holidays', 'id' : null , };
        this.addInitialCategory(initCat);
        initCat = {'name' : 'Shopping list', 'id' : null , };
        this.addInitialCategory(initCat);
    
        let initTodo = new Todo();
        initTodo = {'title' : 'Task1', 'complete': false, 'id' : null , category: 1 };
        this.addInitialTodo(initTodo);
        initTodo = {'title' : 'Task2', 'complete': true, 'id' : null , category: 2 };
        this.addInitialTodo(initTodo);
        initTodo = {'title' : 'Task3', 'complete': true, 'id' : null , category: 1 };
        this.addInitialTodo(initTodo);
      }
    
    }
    
    

3. Adding styles to our app

  1. Open app.component.css. File by default is empty.
  2. Add styles:
    .list {
        border: 1px solid rgba(0, 0, 0, 0.125);
        margin-left: 15px;
        margin-right: 15px;
    }
    
    .strikethrough {
        text-decoration: line-through;
      }
    
      .full-width {
          width: 100%;
      }
    

4. Running application

Run following command ng serve -o. You will see our new application in a browser:

todoapp

Now you can play with our todo app. List on the right side shows the list of our categories and counter informing on how many items is currently assigned to each category.

List of categories

At the bottom of the list, you will find an input which allows us to create a new category. Type some name and press Enter ⏎

New category input

When you click on the category name, list of the item will be shown in the right column:

Todo list

Similarly - there is an input at the bottom which allows you to create a new item. Type the name of a new task and click on an icon.

New todo input

If you make a mistake, you can remove item clicking icon on the right. If task is complete you can click the checkbox on the left side of Todo. This will cross out the item name.

New todo input

Our application is running. Within next lesson, we will analyze, step by step, a different part of our code to get a better understanding of how different Angular functions work.


Next lesson

Spread the word:
Do you need help?: Use our support forum

About author

Dawid Adach
For more than 5 years Dawid was working as an IT Consultant specializing in SOA/EAI/ESB for banking domain. He was gaining experience working in countries like Netherlands, Belgium, Poland and India developing enterprise-class systems for the biggest companies within a domain. Since 2 years as a co-founder of mdbootstrap.com & brandflow.net is using and teaching others technologies like Angular, TypeScript, PHP, AJAX, Mongo, SQL, Hadoop Stack, Virtualization, Automation and many others...
Sign up to follow your progress and get additional benefits