I am new to angular and angular material. I'm using a tutorial to do a small project where I have an angular material autocomplete to filter actors and when I click on one of them, it should be displayed in a mat-table with drag drop feature. So, from the menu - first click on "create movie" to view the actor autocomplete(there's a mat-table to which the selected actor is added). I am not using any database for this feature of actors-autocomplete but using the hard coded actors in the code. But the actors in the autocomplete are not added to the mat-table after I select on it and click on it. But in the browser console, a row is added after I select an actor from the autocomplete but there's no error -
What am I missing here. Entire github code in stackblitz is available in the link below.
My entire project is available in stackblitz Project link
create-movie.component.html
<h2>Create Movie</h2>
<h4>Select the Actors</h4>
<app-actors-autocomplete></app-actors-autocomplete>
create-movie.component.ts
import { Component, OnInit } from '@angular/core';
import { multipleSelectorModel } from '../../utilities/multiple-selector/multiple-selector.model';
import { MoviesService } from '../movies.service';
import { movieCreationDTO } from '../movies.model';
import { map } from 'rxjs/operators';
@Component({
selector: 'app-create-movie',
templateUrl: './create-movie.component.html',
styleUrls: ['./create-movie.component.css'],
})
export class CreateMovieComponent implements OnInit {
constructor() {}
ngOnInit(): void {}
saveChanges(event: Event): void {}
}
actors-autocomplete.component.html
<form>
<mat-form-field>
<input
type="text"
placeholder="Select the actors"
matInput
[formControl]="control"
[matAutocomplete]="auto"
/>
</mat-form-field>
<mat-autocomplete #auto (optionSelected)="optionSelected($event)">
<mat-option *ngFor="let actor of actorsToDisplay" [value]="actor">
<img [src]="actor.picture" /> {{ actor.name }}
</mat-option>
</mat-autocomplete>
</form>
<table
*ngIf="selectedActors.length > 0"
mat-table
[dataSource]="selectedActors"
cdkDropList
[cdkDropListData]="selectedActors"
(cdkDropListDropped)="dropped($event)"
>
<ng-container matColumnDef="picture">
<td mat-cell *matCellDef="let element">
<img [src]="element.picture" style="width: 50px" />
</td>
</ng-container>
<ng-container matColumnDef="name">
<td mat-cell *matCellDef="let element">
{{ element.name }}
</td>
</ng-container>
<ng-container matColumnDef="character">
<td mat-cell *matCellDef="let element">
<mat-form-field appearance="outline" style="margin-top: 10px;">
<mat-label>Character</mat-label>
<input matInput [(ngModel)]="element.character" />
</mat-form-field>
</td>
</ng-container>
<ng-container matColumnDef="actions">
<td mat-cell *matCellDef="let element">
<mat-icon mat-list-icon (click)="remove(element)">close</mat-icon>
</td>
</ng-container>
<tr
mat-row
*matRowDef="let row; columns: columnsToDisplay"
cdkDrag
[cdkDragData]="row"
></tr>
</table>
actors-autocomplete.component.ts
import { actorsMovieDTO } from './../actors.model';
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
import { analyzeAndValidateNgModules } from '@angular/compiler';
import { Component, Input, OnInit, ViewChild } from '@angular/core';
import { FormControl } from '@angular/forms';
import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
import { MatTable } from '@angular/material/table';
import { ActorsService } from '../actors.service';
@Component({
selector: 'app-actors-autocomplete',
templateUrl: './actors-autocomplete.component.html',
styleUrls: ['./actors-autocomplete.component.css'],
})
export class ActorsAutocompleteComponent implements OnInit {
constructor(private actorService: ActorsService) {}
control: FormControl = new FormControl();
// @Input()
// selectedActors : []= [];
// actorsToDisplay:actorsMovieDTO[]=[];
actorsToDisplay = [
{
name: 'Tom Holland',
picture:
'https://moviesapis.blob.core.windows.net/actors/bb1533c8-fe83-4145-8f8f-d1535afbe01e.jpg',
character: '',
},
{
name: 'Chris Hemsworth',
picture:
'https://moviesapis.blob.core.windows.net/actors/f39dd82f-5b41-4d54-887b-8430500bb0e5.jpg',
character: '',
},
{
name: 'Samuel L Jackson',
picture:
'https://moviesapis.blob.core.windows.net/actors/1d99e4df-dfa5-4dde-9b4b-2d197f5fb116.jpg',
character: '',
},
{
name: 'Chris Evans',
picture:
'https://moviesapis.blob.core.windows.net/actors/346b6791-6b61-42b7-8a57-da136463217e.jpg',
character: '',
},
];
selectedActors: any[]=[];
originalActors = this.actorsToDisplay;
columnsToDisplay!: ['picture', 'name', 'character', 'actions'];
@ViewChild(MatTable) table: MatTable<any>;
ngOnInit(): void {
this.control.valueChanges.subscribe((value) => {
this.actorsToDisplay = this.originalActors;
this.actorsToDisplay = this.actorsToDisplay.filter(
(actor) => actor.name.indexOf(value) !== -1
);
});
}
optionSelected(event: MatAutocompleteSelectedEvent) {
console.log(event.option.value);
this.selectedActors.push(event.option.value);
this.control.patchValue('');
// this.control.patchValue('');
if (this.table !== undefined) {
this.table.renderRows();
}
}
remove(actor) {
const index = this.selectedActors.findIndex((a) => a.name === actor.name);
this.selectedActors.splice(index, 1);
this.table.renderRows();
}
dropped(event: CdkDragDrop<any[]>) {
const previousIndex = this.selectedActors.findIndex(
(actor) => actor === event.item.data
);
moveItemInArray(this.selectedActors, previousIndex, event.currentIndex);
this.table.renderRows();
}
}
actors-autocomplete.component.css
form{
width:100%;
max-width: 500px;
}
mat-form-field{
width: 100%;
}
img{
vertical-align: middle;
margin-right: 8px;
width: 35px;
height: 45px;
}
table{
width: 100%;
margin-bottom: 1rem;
}
mat-icon{
cursor: pointer;
}
CodePudding user response:
The issue is with the below property declaration in actors-autocomplete.component.ts
:
columnsToDisplay!: ['picture', 'name', 'character', 'actions'];
It should be initialized with =
as:
columnsToDisplay = ['picture', 'name', 'character', 'actions'];