| 
									
										
										
										
											2018-03-21 17:11:08 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							| 
									
										
										
										
											2020-05-19 12:08:49 -07:00
										 |  |  |  * Copyright Google LLC All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2018-03-21 17:11:08 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-22 10:38:30 -07:00
										 |  |  | import '@angular/core/test/bundling/util/src/reflect_metadata'; | 
					
						
							| 
									
										
										
										
											2018-05-21 08:15:19 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-18 08:05:06 -07:00
										 |  |  | import {CommonModule} from '@angular/common'; | 
					
						
							| 
									
										
										
										
											2018-09-14 15:58:57 -07:00
										 |  |  | import {Component, Injectable, NgModule, ViewEncapsulation, ɵmarkDirty as markDirty, ɵrenderComponent as renderComponent} from '@angular/core'; | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 16:02:10 -07:00
										 |  |  | class Todo { | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  |   editing: boolean; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-18 16:38:33 -07:00
										 |  |  |   // TODO(issue/24571): remove '!'.
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   private _title!: string; | 
					
						
							|  |  |  |   get title() { | 
					
						
							|  |  |  |     return this._title; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   set title(value: string) { | 
					
						
							|  |  |  |     this._title = value.trim(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   constructor(title: string, public completed: boolean = false) { | 
					
						
							|  |  |  |     this.editing = false; | 
					
						
							|  |  |  |     this.title = title; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-03-21 17:11:08 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-12 16:03:05 -07:00
										 |  |  | @Injectable({providedIn: 'root'}) | 
					
						
							| 
									
										
										
										
											2018-06-20 16:02:10 -07:00
										 |  |  | class TodoStore { | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  |   todos: Array<Todo> = [ | 
					
						
							|  |  |  |     new Todo('Demonstrate Components'), | 
					
						
							|  |  |  |     new Todo('Demonstrate Structural Directives', true), | 
					
						
							|  |  |  |     new Todo('Demonstrate NgModules'), | 
					
						
							|  |  |  |     new Todo('Demonstrate zoneless change detection'), | 
					
						
							|  |  |  |     new Todo('Demonstrate internationalization'), | 
					
						
							| 
									
										
										
										
											2018-03-21 17:11:08 -07:00
										 |  |  |   ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  |   private getWithCompleted(completed: boolean) { | 
					
						
							|  |  |  |     return this.todos.filter((todo: Todo) => todo.completed === completed); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-03-21 17:11:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   allCompleted() { | 
					
						
							|  |  |  |     return this.todos.length === this.getCompleted().length; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   setAllTo(completed: boolean) { | 
					
						
							|  |  |  |     this.todos.forEach((t: Todo) => t.completed = completed); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   removeCompleted() { | 
					
						
							|  |  |  |     this.todos = this.getWithCompleted(false); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   getRemaining() { | 
					
						
							|  |  |  |     return this.getWithCompleted(false); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-03-21 17:11:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   getCompleted() { | 
					
						
							|  |  |  |     return this.getWithCompleted(true); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-03-21 17:11:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   toggleCompletion(todo: Todo) { | 
					
						
							|  |  |  |     todo.completed = !todo.completed; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-03-21 17:11:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   remove(todo: Todo) { | 
					
						
							|  |  |  |     this.todos.splice(this.todos.indexOf(todo), 1); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |   add(title: string) { | 
					
						
							|  |  |  |     this.todos.push(new Todo(title)); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-03-21 17:11:08 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @Component({ | 
					
						
							|  |  |  |   selector: 'todo-app', | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  |   // TODO(misko): make this work with `[(ngModel)]`
 | 
					
						
							| 
									
										
										
										
											2018-07-31 11:14:06 -07:00
										 |  |  |   encapsulation: ViewEncapsulation.None, | 
					
						
							| 
									
										
										
										
											2018-03-21 17:11:08 -07:00
										 |  |  |   template: `
 | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  |   <section class="todoapp"> | 
					
						
							|  |  |  |     <header class="header"> | 
					
						
							|  |  |  |       <h1>todos</h1> | 
					
						
							| 
									
										
										
										
											2018-06-18 08:05:06 -07:00
										 |  |  |       <input class="new-todo" placeholder="What needs to be done?" autofocus="" | 
					
						
							|  |  |  |              [value]="newTodoText" | 
					
						
							| 
									
										
										
										
											2018-09-14 15:58:57 -07:00
										 |  |  |              (keyup)="$event.code == 'Enter' ? addTodo() : updateNewTodoValue($event.target.value)"> | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  |     </header> | 
					
						
							|  |  |  |     <section *ngIf="todoStore.todos.length > 0" class="main"> | 
					
						
							| 
									
										
										
										
											2018-06-18 08:05:06 -07:00
										 |  |  |       <input *ngIf="todoStore.todos.length" | 
					
						
							|  |  |  |              #toggleall class="toggle-all" type="checkbox" | 
					
						
							|  |  |  |              [checked]="todoStore.allCompleted()" | 
					
						
							| 
									
										
										
										
											2018-09-14 15:58:57 -07:00
										 |  |  |              (click)="toggleAllTodos(toggleall.checked)"> | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  |       <ul class="todo-list"> | 
					
						
							| 
									
										
										
										
											2018-06-18 08:05:06 -07:00
										 |  |  |         <li *ngFor="let todo of todoStore.todos" | 
					
						
							|  |  |  |             [class.completed]="todo.completed" | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:20 -07:00
										 |  |  |             [class.editing]="todo.editing"> | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  |           <div class="view"> | 
					
						
							| 
									
										
										
										
											2018-06-18 08:05:06 -07:00
										 |  |  |             <input class="toggle" type="checkbox" | 
					
						
							|  |  |  |                    (click)="toggleCompletion(todo)" | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:20 -07:00
										 |  |  |                    [checked]="todo.completed"> | 
					
						
							|  |  |  |             <label (dblclick)="editTodo(todo)">{{todo.title}}</label> | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  |             <button class="destroy" (click)="remove(todo)"></button> | 
					
						
							|  |  |  |           </div> | 
					
						
							| 
									
										
										
										
											2018-06-18 08:05:06 -07:00
										 |  |  |           <input *ngIf="todo.editing" | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  |                  class="edit" #editedtodo | 
					
						
							| 
									
										
										
										
											2018-06-18 08:05:06 -07:00
										 |  |  |                  [value]="todo.title" | 
					
						
							| 
									
										
										
										
											2019-10-12 18:38:47 +02:00
										 |  |  |                  (blur)="updateEditedTodoValue(todo, editedtodo.value)" | 
					
						
							|  |  |  |                  (keyup)="updateEditedTodoValue(todo, $event.target.value)" | 
					
						
							|  |  |  |                  (keyup)="$event.code == 'Enter' && updateEditedTodoValue(todo, editedtodo.value)" | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  |                  (keyup)="$event.code == 'Escape' && cancelEditingTodo(todo)"> | 
					
						
							|  |  |  |         </li> | 
					
						
							|  |  |  |       </ul> | 
					
						
							|  |  |  |     </section> | 
					
						
							|  |  |  |     <footer *ngIf="todoStore.todos.length > 0" class="footer"> | 
					
						
							|  |  |  |       <span class="todo-count"> | 
					
						
							|  |  |  |         <strong>{{todoStore.getRemaining().length}}</strong> | 
					
						
							|  |  |  |         {{todoStore.getRemaining().length == 1 ? 'item' : 'items'}} left | 
					
						
							|  |  |  |       </span> | 
					
						
							| 
									
										
										
										
											2018-06-18 08:05:06 -07:00
										 |  |  |       <button *ngIf="todoStore.getCompleted().length > 0" | 
					
						
							|  |  |  |               class="clear-completed" | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  |               (click)="removeCompleted()"> | 
					
						
							|  |  |  |         Clear completed | 
					
						
							|  |  |  |       </button> | 
					
						
							|  |  |  |     </footer> | 
					
						
							|  |  |  |   </section> | 
					
						
							| 
									
										
										
										
											2018-04-04 13:12:27 -07:00
										 |  |  |   `,
 | 
					
						
							| 
									
										
										
										
											2018-04-10 20:57:20 -07:00
										 |  |  |   // TODO(misko): switch over to OnPush
 | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  |   // changeDetection: ChangeDetectionStrategy.OnPush
 | 
					
						
							| 
									
										
										
										
											2018-03-21 17:11:08 -07:00
										 |  |  | }) | 
					
						
							| 
									
										
										
										
											2018-06-20 16:02:10 -07:00
										 |  |  | class ToDoAppComponent { | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  |   newTodoText = ''; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-12 16:03:05 -07:00
										 |  |  |   constructor(public todoStore: TodoStore) {} | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 15:58:57 -07:00
										 |  |  |   cancelEditingTodo(todo: Todo) { | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  |     todo.editing = false; | 
					
						
							| 
									
										
										
										
											2018-09-14 15:58:57 -07:00
										 |  |  |     markDirty(this); | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 15:58:57 -07:00
										 |  |  |   finishUpdatingTodo(todo: Todo, editedTitle: string) { | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  |     editedTitle = editedTitle.trim(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (editedTitle.length === 0) { | 
					
						
							| 
									
										
										
										
											2018-09-14 15:58:57 -07:00
										 |  |  |       this.remove(todo); | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-21 17:11:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  |     todo.title = editedTitle; | 
					
						
							| 
									
										
										
										
											2018-09-14 15:58:57 -07:00
										 |  |  |     this.cancelEditingTodo(todo); | 
					
						
							| 
									
										
										
										
											2018-03-21 17:11:08 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 15:58:57 -07:00
										 |  |  |   editTodo(todo: Todo) { | 
					
						
							|  |  |  |     todo.editing = true; | 
					
						
							|  |  |  |     markDirty(this); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 15:58:57 -07:00
										 |  |  |   removeCompleted() { | 
					
						
							|  |  |  |     this.todoStore.removeCompleted(); | 
					
						
							|  |  |  |     markDirty(this); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 15:58:57 -07:00
										 |  |  |   toggleCompletion(todo: Todo) { | 
					
						
							|  |  |  |     this.todoStore.toggleCompletion(todo); | 
					
						
							|  |  |  |     markDirty(this); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 15:58:57 -07:00
										 |  |  |   remove(todo: Todo) { | 
					
						
							|  |  |  |     this.todoStore.remove(todo); | 
					
						
							|  |  |  |     markDirty(this); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-04-06 10:29:22 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   addTodo() { | 
					
						
							|  |  |  |     if (this.newTodoText.trim().length) { | 
					
						
							|  |  |  |       this.todoStore.add(this.newTodoText); | 
					
						
							|  |  |  |       this.newTodoText = ''; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-09-14 15:58:57 -07:00
										 |  |  |     markDirty(this); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   toggleAllTodos(checked: boolean) { | 
					
						
							|  |  |  |     this.todoStore.setAllTo(checked); | 
					
						
							|  |  |  |     markDirty(this); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   updateEditedTodoValue(todo: Todo, value: string) { | 
					
						
							|  |  |  |     todo.title = value; | 
					
						
							|  |  |  |     markDirty(this); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   updateNewTodoValue(value: string) { | 
					
						
							|  |  |  |     this.newTodoText = value; | 
					
						
							|  |  |  |     markDirty(this); | 
					
						
							| 
									
										
										
										
											2018-03-21 17:11:08 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-31 15:50:02 -07:00
										 |  |  | @NgModule({declarations: [ToDoAppComponent], imports: [CommonModule]}) | 
					
						
							| 
									
										
										
										
											2018-06-20 16:02:10 -07:00
										 |  |  | class ToDoAppModule { | 
					
						
							| 
									
										
										
										
											2018-03-21 17:11:08 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-03 16:34:25 +01:00
										 |  |  | renderComponent(ToDoAppComponent); |