Newbie here on Angular. I have an input class Foo with a list of books with Book class having Id, Title and Description property. I display it in a table with input so user can add, edit or delete book list. There is a button somewhere that adds and deletes a book. This is working fine. I wanted to add a sort but it's not working. I added MatSort and Sort in the appmodule. I put the sort code block from Angular itself. What am I doing wrong? Should I change this in a MatTable instead of looping through a form array? If so how can I do that with input instead of displaying per data as variable {{element.title}} etc? Appreciate all the help. TS @Input() foo: Foo; @ViewChild(MatSort, {static: true}) sort: MatSort; bookForm: FormArray; orderForm: FormGroup; bookList !: Book[]; bookSorted : Book[]; initForm() { this.orderForm= this._formBuilder.group( { customerForm: this._formBuilder.array( [] ), bookForm: this._formBuilder.array( [] ) } ); this.addedBooks() this.bookList = this.foo.Books; } addedBooks() { this.bookForm= this.orderForm.get( 'bookForm' ) as FormArray; this.bookForm.clear(); let _bookForm = this.foo.books?.map( _book => this.addBook( _book ) ); _bookForm?.forEach( _addBook => this.bookForm.push( _addBook ) ); } addBook( _book) { return this._formBuilder.group( { title: new FormControl( _book?.title), description: new FormControl( _book?.description ), id: new FormControl( _book?.id ?? Guid.EMPTY ), } ); } get bookFormControls() { return ( this.orderForm.get( 'bookForm' ) as FormArray ).controls; } sortBook(sort: Sort) { const data = this.bookList.slice(); if (!sort.active || sort.direction == '') { this.bookSorted = data; return; } this.bookSorted = data.sort((a, b) => { let isAsc = sort.direction == 'asc'; switch (sort.active) { case 'title': return this.compare(a.title, b.title, isAsc); case 'description': return this.compare(+a.description, +b.description, isAsc); default: return 0; } }); } compare(a, b, isAsc) { return (a < b ? -1 : 1) * (isAsc ? 1 : -1); } removeBooksAt( index ) { this.dialogName = "Book" this.modalRef = this.dialog.open( this.deleteBook, { width: '600px', } ); this.modalRef.afterClosed().subscribe( res => { if ( res ) this.bookForm.removeAt( index ); } ); } addNewBook() { let formValue = this.orderForm.controls['bookForm'] as FormArray; formValue.status == 'VALID' ? this.createBooksForm() : this.showToast(); } createBooksForm(data?: any) { this.booksForm = this.orderForm.get( 'booksForm ' ) as FormArray; this.booksForm .push( this.addBooksControls(data) ); } addBooksControls(data?: any): FormGroup { return this._formBuilder.group( { title: [data?.title ??'', Validators.required], description: [data?.description ??'', Validators.required], id: [data?.id ??Guid.EMPTY] } ); } HTML <!--Mat Sort Test--> <fieldset> <div> <legend>Books</legend> <table matSort (matSortChange)="sortBook($event)" class="card-table"> <thead class="primary-color"> <tr> <th mat-sort-header="title"> Book Title </th> <th mat-sort-header="description"> Description </th> <th class="colums-name"> Actions </th> </tr> </thead> <tbody> <tr class="margin-1" formArrayName="bookForm" *ngFor="let group of bookFormControls; let _i = index;"> <td [formGroupName]="_i"> <input type="text" formControlName="title" class="margin-1 readonly" placeholder="Add title"> </td> <td [formGroupName]="_i"> <input type="text" formControlName="description" class="margin-1 readonly" placeholder="Add description"> <input type="hidden" formControlName="id"> </td> <td style="text-align: center;"> <i (click)="removeBooksAt(_i, 'Title')" class="fa fa-trash margin-right-mini" style="color:darkgrey; font-size: xx-large;;" aria-hidden="true"></i> </td> </tr> </tbody> </table> </div> </fieldset> Continue reading...