|  |  |  | @ -930,4 +930,134 @@ When you run the application, you can see the *Author* column on the table: | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |  | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | ### Create/Edit Forms | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | The next step is to add an Author selection (dropdown) to the create/edit forms. The final UI will look like the one shown below: | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |  | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | Added the Author dropdown as the first element in the form. | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | Open the `/src/app/book/book.component.ts` and and change the content as shown below: | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | ````typescript | 
			
		
	
		
			
				
					|  |  |  |  | import { ListService, PagedResultDto } from '@abp/ng.core'; | 
			
		
	
		
			
				
					|  |  |  |  | import { Component, OnInit } from '@angular/core'; | 
			
		
	
		
			
				
					|  |  |  |  | import { BookService, BookDto, bookTypeOptions, AuthorLookupDto } from '@proxy/books'; | 
			
		
	
		
			
				
					|  |  |  |  | import { FormGroup, FormBuilder, Validators } from '@angular/forms'; | 
			
		
	
		
			
				
					|  |  |  |  | import { NgbDateNativeAdapter, NgbDateAdapter } from '@ng-bootstrap/ng-bootstrap'; | 
			
		
	
		
			
				
					|  |  |  |  | import { ConfirmationService, Confirmation } from '@abp/ng.theme.shared'; | 
			
		
	
		
			
				
					|  |  |  |  | import { Observable } from 'rxjs'; | 
			
		
	
		
			
				
					|  |  |  |  | import { map } from 'rxjs/operators'; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | @Component({ | 
			
		
	
		
			
				
					|  |  |  |  |   selector: 'app-book', | 
			
		
	
		
			
				
					|  |  |  |  |   templateUrl: './book.component.html', | 
			
		
	
		
			
				
					|  |  |  |  |   styleUrls: ['./book.component.scss'], | 
			
		
	
		
			
				
					|  |  |  |  |   providers: [ListService, { provide: NgbDateAdapter, useClass: NgbDateNativeAdapter }], | 
			
		
	
		
			
				
					|  |  |  |  | }) | 
			
		
	
		
			
				
					|  |  |  |  | export class BookComponent implements OnInit { | 
			
		
	
		
			
				
					|  |  |  |  |   book = { items: [], totalCount: 0 } as PagedResultDto<BookDto>; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   form: FormGroup; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   selectedBook = {} as BookDto; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   authors$: Observable<AuthorLookupDto[]>; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   bookTypes = bookTypeOptions; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   isModalOpen = false; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   constructor( | 
			
		
	
		
			
				
					|  |  |  |  |     public readonly list: ListService, | 
			
		
	
		
			
				
					|  |  |  |  |     private bookService: BookService, | 
			
		
	
		
			
				
					|  |  |  |  |     private fb: FormBuilder, | 
			
		
	
		
			
				
					|  |  |  |  |     private confirmation: ConfirmationService | 
			
		
	
		
			
				
					|  |  |  |  |   ) { | 
			
		
	
		
			
				
					|  |  |  |  |     this.authors$ = bookService.getAuthorLookup().pipe(map((r) => r.items)); | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   ngOnInit() { | 
			
		
	
		
			
				
					|  |  |  |  |     const bookStreamCreator = (query) => this.bookService.getList(query); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     this.list.hookToQuery(bookStreamCreator).subscribe((response) => { | 
			
		
	
		
			
				
					|  |  |  |  |       this.book = response; | 
			
		
	
		
			
				
					|  |  |  |  |     }); | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   createBook() { | 
			
		
	
		
			
				
					|  |  |  |  |     this.selectedBook = {} as BookDto; | 
			
		
	
		
			
				
					|  |  |  |  |     this.buildForm(); | 
			
		
	
		
			
				
					|  |  |  |  |     this.isModalOpen = true; | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   editBook(id: string) { | 
			
		
	
		
			
				
					|  |  |  |  |     this.bookService.get(id).subscribe((book) => { | 
			
		
	
		
			
				
					|  |  |  |  |       this.selectedBook = book; | 
			
		
	
		
			
				
					|  |  |  |  |       this.buildForm(); | 
			
		
	
		
			
				
					|  |  |  |  |       this.isModalOpen = true; | 
			
		
	
		
			
				
					|  |  |  |  |     }); | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   buildForm() { | 
			
		
	
		
			
				
					|  |  |  |  |     this.form = this.fb.group({ | 
			
		
	
		
			
				
					|  |  |  |  |       authorId: [this.selectedBook.authorId || null, Validators.required], | 
			
		
	
		
			
				
					|  |  |  |  |       name: [this.selectedBook.name || null, Validators.required], | 
			
		
	
		
			
				
					|  |  |  |  |       type: [this.selectedBook.type || null, Validators.required], | 
			
		
	
		
			
				
					|  |  |  |  |       publishDate: [ | 
			
		
	
		
			
				
					|  |  |  |  |         this.selectedBook.publishDate ? new Date(this.selectedBook.publishDate) : null, | 
			
		
	
		
			
				
					|  |  |  |  |         Validators.required, | 
			
		
	
		
			
				
					|  |  |  |  |       ], | 
			
		
	
		
			
				
					|  |  |  |  |       price: [this.selectedBook.price || null, Validators.required], | 
			
		
	
		
			
				
					|  |  |  |  |     }); | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   save() { | 
			
		
	
		
			
				
					|  |  |  |  |     if (this.form.invalid) { | 
			
		
	
		
			
				
					|  |  |  |  |       return; | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     const request = this.selectedBook.id | 
			
		
	
		
			
				
					|  |  |  |  |       ? this.bookService.update(this.selectedBook.id, this.form.value) | 
			
		
	
		
			
				
					|  |  |  |  |       : this.bookService.create(this.form.value); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     request.subscribe(() => { | 
			
		
	
		
			
				
					|  |  |  |  |       this.isModalOpen = false; | 
			
		
	
		
			
				
					|  |  |  |  |       this.form.reset(); | 
			
		
	
		
			
				
					|  |  |  |  |       this.list.get(); | 
			
		
	
		
			
				
					|  |  |  |  |     }); | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   delete(id: string) { | 
			
		
	
		
			
				
					|  |  |  |  |     this.confirmation.warn('::AreYouSureToDelete', 'AbpAccount::AreYouSure').subscribe((status) => { | 
			
		
	
		
			
				
					|  |  |  |  |       if (status === Confirmation.Status.confirm) { | 
			
		
	
		
			
				
					|  |  |  |  |         this.bookService.delete(id).subscribe(() => this.list.get()); | 
			
		
	
		
			
				
					|  |  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |  |     }); | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | ```` | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | * Added imports for the `AuthorLookupDto`, `Observable` and `map`. | 
			
		
	
		
			
				
					|  |  |  |  | * Added `authors$: Observable<AuthorLookupDto[]>;` field after the `selectedBook`. | 
			
		
	
		
			
				
					|  |  |  |  | * Added `this.authors$ = bookService.getAuthorLookup().pipe(map((r) => r.items));` into the constructor. | 
			
		
	
		
			
				
					|  |  |  |  | * Added ` authorId: [this.selectedBook.authorId || null, Validators.required],` into the `buildForm()` function. | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | Open the `/src/app/book/book.component.html` and add the following form group just before the book name form group: | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | ````html | 
			
		
	
		
			
				
					|  |  |  |  | <div class="form-group"> | 
			
		
	
		
			
				
					|  |  |  |  |   <label for="author-id">Author</label><span> * </span> | 
			
		
	
		
			
				
					|  |  |  |  |   <select class="form-control" id="author-id" formControlName="authorId"> | 
			
		
	
		
			
				
					|  |  |  |  |     <option [ngValue]="null">Select author</option> | 
			
		
	
		
			
				
					|  |  |  |  |     <option [ngValue]="author.id" *ngFor="let author of authors$ | async"> | 
			
		
	
		
			
				
					|  |  |  |  |       {%{{{ author.name }}}%} | 
			
		
	
		
			
				
					|  |  |  |  |     </option> | 
			
		
	
		
			
				
					|  |  |  |  |   </select> | 
			
		
	
		
			
				
					|  |  |  |  | </div> | 
			
		
	
		
			
				
					|  |  |  |  | ```` | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | That's all. Just run the application and try to create or edit an author. | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | {{end}} |