Unable to get the Angular Material Auto Complete Values - javascript

i am trying to Create a autocomplete filter and from a array and when i am trying to use it is displaying to lower case is now a function
below is my code
<form class="example-form">
<mat-form-field class="example-full-width">
<input type="text"
placeholder="Pick one"
matInput
[formControl]="myControl"
[matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let option of filteredOptions | async" [value]="option">
{{option.Address}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</form>
.ts code:
myControl = new FormControl();
options:any [] = [
{
"Id": "SO5",
"Address": "Wall Street. New York City"
},
{
"Id": "65",
"Address": "Wall Street. New York City"
},
{
"buyerId": "63g",
"Address": "Dallas"
}
]
filteredOptions: Observable<any[]>;
ngOnInit() {
this.filteredOptions = this.myControl.valueChanges
.pipe(
startWith(''),
map(value => this._filter(value))
);
}
private _filter(value:any):any[] {
console.log(value);
const filterValue = value.toLowerCase();
return this.options.filter(option => option.toLowerCase().includes(filterValue));
}
}
below is my stackblitz link https://stackblitz.com/edit/angular-ygzpcz

options is an array of objects. There is no toLowerCase method on object.
You should be using option.Address instead:
return this.options.filter(option => option.Address.toLowerCase()
^^^^^^^^^
Also, in case of objects you should create displayWith method in order to map object to desired diplayed value:
html
<mat-autocomplete ... [displayWith]="displayWith">
ts
displayWith(item: any) {
return item ? item.Address : ''
}
Forked Stackblitz

Related

How to get array from Array of objects to get a new array as <mat-autocomplete> is not working on objects

I need to extract DISPLAY_NAME into a saparate array from Amenity_Listin order to work with , but its not working.
HTML
<mat-form-field *ngIf="element.IS_EDIT" appearance="outline">
<input #AmenityInput type="text" placeholder="Pick one" aria-label="Number" matInput [formControl]="myControl" [(ngModel)]="element.NEW_AMENITY_NAME" [matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete" class="" (optionSelected)='onSelect($event,i)'>
<mat-option *ngFor="let item of filteredOptions | async" [value]="item">
{{item}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
TS-
export class ViewAssignedSeatsComponent implements OnInit {
myControl = new FormControl('');
filteredOptions: Observable<string[]>;
displayName : string[];
ngOnInit(): void {
console.log(this.AmenityList);
this.displayName = this.AmenityList.map(a=>a.DISPLAY_NAME);
console.log(this.displayName , typeof(this.displayName));// here type is always objects though I need array
this.filteredOptions = this.myControl.valueChanges.pipe(
startWith(''),
map(value => this._filter(value || '')),
);
}
private _filter(value: string): string[] {
const filterValue = value.toLowerCase();
return this.AmenityList.filter(option => option.DISPLAY_NAME.toLowerCase().includes(filterValue));
}
onSelect(event:any, index:any){
console.log("called", event.target.value);// here I'm getting undefined , also after search the new value is lost.
}
}
I need just filter on mat-select using mat-autocomplete. But I'm unable to get the display names in array to have them as options for
selection and Search. I need it in this.displayNames as array of
string type instead of object.
Attaching image for Amenity_list.

Angular - Show dropdown after write # on input field

My Objective is to show a dropdown menu when i start to write # on the input field.
My Component
myControl: FormControl = new FormControl();
options = [
'One',
'Two',
'Three'
];
filteredOptions: Observable<string[]>;
ngOnInit() {
this.filteredOptions = this.myControl.valueChanges
.pipe(
startWith('#'),
map(val => val.length >= 1 ? this.filter(val): [])
);
}
filter(val: string): string[] {
return this.options.filter(option =>
option.toLowerCase().indexOf(val.toLowerCase()) === 0);
console.log(this.options)
}
This is what i have done, but its not working.
HTML
<form class="example-form">
<mat-form-field class="example-full-width">
<input #inputField type="text" placeholder="Pick one" aria-label="Number" matInput [formControl]="myControl" [matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete">
<mat-option *ngFor="let option of filteredOptions | async" [value]="option">
{{ option }}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</form>
Your subscription is working great.
You just forget to escape the # in filter function since you don't have an # in your option List.
Try this :
filter(val: string): string[] {
return this.options.filter(option =>
option.toLowerCase().indexOf(val.toLowerCase().replace('#', '')) === 0);
}
Just register to the change event on your input - for example:
(change)='handlerMethode($event)'
Check input for index of # and if you find do what you want.

Wrong onselect display ? Angular 2+

When I select an option instead of showing me the name it shows me the id. That's because I bind [value] = "option.id". I'm sending an id to the server and want to show name.
<mat-form-field class="example-full-width">
<input
matInput
placeholder="Pretrazite proizvod koji zelite naruciti samo kucajte pocetna slova"
formControlName="id"
[matAutocomplete] = "auto"
>
<mat-autocomplete #auto="matAutocomplete" >
<mat-option *ngFor="let option of allProducts; let i = index" [value]="option.id" (onSelectionChange)="getPosts(i)">
{{ option.name }}
</mat-option>
</mat-autocomplete>
</mat-form-field>
getProducts() {
this.product.getAllProducts().subscribe((data: any) => {
this.allProducts = data.products;
console.log(data.products);
});
}
I also have (onSelectionChange) = "getPosts (i)" function
getPosts(index){
this.selectedProduct = index;
}
My question is how do I forward the id and display the name in mat-autocomplete-mat-option options.
I suppose this onchange is my function, the problem is that I have dynamic fields
Looking my other code
ngOnInit() {
this.getProducts();
this.form = this.fb.group({
address: [null],
phone: [null],
city: [null],
data: this.fb.array([this.createContact()])
});
this.contactList = this.form.get('data') as FormArray;
}
createContact(): FormGroup {
return this.fb.group({
id: [this.selectedProduct],
quantity: [null]
});
In case you need the whole code, ask me, but I didn't want to overwhelm you with a lot of code.
You can do something like this, it should help you:
<mat-autocomplete #auto="matAutocomplete" >
<mat-option *ngFor="let option of allProducts; let i = index" [value]="selectedProduct.name" (onSelectionChange)="getPosts(option)">
{{ option.name }}
</mat-option>
</mat-autocomplete>

Filter in the drop down data -Angular 6

I want Angular app to filter data from the dropdown, list of products are associated with the product number. Below is the JSON structure.
component.ts
productlistArray = [{
number: "1",
productlist: [
{ name: "product_1_0" },
{ name: "product_1_1" }
]
}, {
number: "2",
productlist: [
{ name: "product_2_0" },
{ name: "product_2_1" }
]
}];
onclickx() {
this.consoleMessages += "called this function";
}
I have an input box (to search by product). when I type product number it must list only products under product number.
component.html
<td>
<div class="form-group">
<input type="text" class="form-control" placeholder="Search By Product No" style="width:300px" [(ngModel)]="searchTerm"/>
</div>
<div class="form-group">
<mat-select (selectionChange)="onclickx($event.value)">
<mat-option *ngFor="let product of productlistArray" [value]="product.number">
{{product.productlist}}
</mat-option>
</mat-select>
</div>
</td>
pipe.ts
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name:"ProductFilter",
pure:true
})
export class ProductFilter implements PipeTransform {
transform(data: any[], searchTerm: string): any[] {
return data.filter(productlistArray =>(productlistArray.number == searchTerm));
}
}
Initially, when there is no searchTerm entered, it will be undefined so the filter will not return any data. Add a condition to return all data if there is no searchTerm. As mentioned by #AJT82 in the comments, this logic should also be placed in the component.
filteredProducts: any; // You should ideally create an interface instead
searchTerm: string;
filter() {
this.filteredProducts = this.searchTerm ? this.productlistArray.filter(productlistArray => productlistArray.number == this.searchTerm) : this.productlistArray;
}
Note: For formControl, use valueChanges to achieve the same
Then call this function on change of the input
<input type="text" class="form-control" [(ngModel)]="searchTerm" (change)="filter()" placeholder="Search By Product No" style="width: 300px;" />
And use filteredProducts in your template
<mat-form-field>
<mat-select placeholder="Product" (selectionChange)="onclickx($event.value)">
<mat-option *ngFor="let product of filteredProducts" [value]="product.number">
{{product.productlist}}
</mat-option>
</mat-select>
</mat-form-field>

Duplicate objects stored in array while adding an element

I am developing an application in angular as a beginner. The application takes notes and stores them in DB.
I am facing an issue during addition. If there are no existing data in DB and I have added two new notes, both the notes are displayed as same in UI. Although the new note and old note is present in DB.
I observed one thing. The data returned from DB is in JSON format.
On adding new data, the note array is displayed as -
0: {}
1: {}
2: Note{}
3: Note{}
NoteService -
export class NotesService {
private baseURL = 'http://localhost:8082/api/v1/note';
notes: Note[];
notesSubject: BehaviorSubject<Note[]>;
constructor(private http: HttpClient) {
this.notes = [];
this.notesSubject = new BehaviorSubject<Note[]>([]);
}
private extractData(res: Response) {
let body = res;
return body;
}
fetchNotesFromServer(): Observable<Note[]> {
return this.http.get(`${this.baseURL}/${sessionStorage.getItem("userId")}`)
.map(this.extractData)
.catch(this.handleErrorObservable);
;
}
getNotes(): BehaviorSubject<Note[]> {
this.fetchNotesFromServer().subscribe(
notes => { this.notes = notes; this.notesSubject.next(this.notes) },
error => this.handleErrorObservable(error));
return this.notesSubject;
}
addNote(note: Note): Observable<Object> {
return this.http.post(this.baseURL, note, { observe: 'response' });
}
private handleErrorObservable(error: HttpErrorResponse | any) {
console.error(error.message || error);
return Observable.throw(new HttpErrorResponse(error));
}
}
NoteTakerComponent : addNote() -
addNote(): void {
this.errMessage = '';
if (this.validateNote()) {
this.note.noteCreatedBy = sessionStorage.getItem("userId");
this.note.noteTitle = this.noteTitle;
this.note.noteContent = this.noteContent;
this.note.noteStatus = this.state;
this.note.category = this.editCategory;
this.note.reminder = this.editReminder;
let maxId = 0;
if (this.noteService.notes.length > 0) {
this.noteService.notes.forEach(note => {
if (note.noteId > maxId) {
maxId = note.noteId;
}
});
}
this.note.noteId = ++maxId;
this.noteService.addNote(this.note).subscribe(response => {
this.noteService.notes.push(this.note);
this.noteService.notesSubject.next(this.noteService.notes);
console.log('note taker', this.noteService.notes);
this.reset();
},
error => this.handleErrorResponse(error));
}
}
NoteTaker view -
<!-- Expansion panel to add new notes -->
<div class="keep-note-expansion-panel">
<mat-accordion>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>Take a note</mat-panel-title>
</mat-expansion-panel-header>
<div class="keep-note-form-container">
<mat-form-field>
<input matInput class="note-full-width form-control" name="title" placeholder="title" [(ngModel)]="noteTitle"
required>
</mat-form-field>
<mat-form-field>
<textarea matInput class="note-full-width form-control" name="text" placeholder="text"
[(ngModel)]="noteContent" required></textarea>
</mat-form-field>
<mat-form-field>
<mat-select name="Status" placeholder="Select state" [(ngModel)]="state">
<mat-option *ngFor="let state of states" [value]="state">
{{ state }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-select name="category" placeholder="Select Category" [(ngModel)]="editCategory">
<mat-option *ngFor="let category of categories" [value]="category">
{{ category.categoryName }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-select name="reminder" placeholder="Select Reminder" [(ngModel)]="editReminder" multiple>
<mat-option *ngFor="let reminder of reminders" [value]="reminder">
{{ reminder.reminderName }}
</mat-option>
</mat-select>
</mat-form-field>
<button mat-button (click)="addNote()">Done</button>
</div>
</mat-expansion-panel>
</mat-accordion>
</div>
NoteView Component -
export class NoteViewComponent implements OnInit {
notes: Note[];
errorMessage: String;
constructor(private noteService: NotesService) {
}
ngOnInit(): void {
this.noteService.getNotes().subscribe(
notes => {
this.notes = notes;
console.log('note view', this.notes);
},
error => this.handleErrorResponse(error));
}
}
Expected result is to show newly added notes with the old notes.
There was a basic error where the same note object was modified instead of creating a new object.
Modified NoteTaker component -
addNote(): void {
this.errMessage = '';
this.note = new Note();
if (this.validateNote()) {
this.note.noteCreatedBy = sessionStorage.getItem("userId");
this.note.noteTitle = this.noteTitle;
this.note.noteContent = this.noteContent;
this.note.noteStatus = this.state;
this.note.category = this.editCategory;
this.note.reminder = this.editReminder;
let maxId = 0;
if (this.noteService.notes.length > 0) {
this.noteService.notes.forEach(note => {
if (note.noteId > maxId) {
maxId = note.noteId;
}
});
}
this.note.noteId = ++maxId;
this.noteService.addNote(this.note).subscribe(response => {
this.noteService.notes.push(this.note);
this.noteService.notesSubject.next(this.noteService.notes);
console.log('note taker', this.noteService.notes);
this.reset();
},
error => this.handleErrorResponse(error));
}
}

Categories