Implement multiple autocompletes for one input - javascript

I currently have an input field that has an autocomplete, I’m trying to have essentially a two stage autocomplete for each entered item, for example typing I would show IP Address, selecting that enters “ipAddress=“ into the input, I would then like to display another autocomplete in the same input based on the selected option to display the available addresses. Then they would add a comma and repeat to add any other filters. I just am not sure what this would be called or how to implement this so any tips or ideas would be greatly appreciated

Try something like this:
TS:
itemList: any[] = [
{ name: "item1", IPForm: new FormControl(), AnotherListValue: [], AnotherForm: new FormControl() },
{ name: "item2", IPForm: new FormControl(), AnotherListValue: [], AnotherForm: new FormControl() }
];
// Fill my another value regarding to selected IP
onSelectedIP(selected: any, item: any) {
this.myService.getListValue(selected.IP).subscribe(result => item.AnotherListValue = result);
}
HTML
<div *ngFor="let item of itemList">
<mat-form-field>
<input type="text" placeholder="Select IP" matInput [matAutocomplete]="itm" [formControl]="item.IPForm">
<mat-autocomplete autoActiveFirstOption #itm="matAutocomplete" [displayWith]="displayFn" (optionSelected)="onSelectedIP($event.option.value, item)">
<mat-option *ngFor="let option of IPList | async" [value]="option">
{{option.IP}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</div>
You just need to add second auto-complete and so on

Related

show/hide divs based on selecting option

I have a select with some filters, every filter should be connected to a div (in the first moment they are hidden, i think with *ngIf, but im not sure how to integrate the it with my code) with his specific functionality. In my project i have the possibility to select which filter i wanna show.
component.ts:
object with filters:
filters: Filter[] = [
{value: 'textSearch', name: 'Denominazione', selected: false},
{value: 'internalReferent', name: 'Referente interno', selected: false},
{value: 'supplierSignUpTimestamp', name: 'Data iscrizione', selected: false},
{value: 'internalReferent', name: 'Merceologia', selected: false},
{value: 'internalReferent', name: 'Sede operativa', selected: false},
{value: 'supplierOperationalHQ', name: 'Stato', selected: false},
]
constructor(private fb: FormBuilder) {
this.supplierFilterForm = this.fb.group({
filter: ['']
});
}
function for toggle:
toggleSelected() {
let filterSelected = this.supplierFilterForm.controls['filter'].value;
let i = this.filters.findIndex(x => x.name == filterSelected);
console.log(filterSelected)
console.log(i)
if (filterSelected == this.filters[i].name) {
this.filters[i].selected = !this.filters[i].selected;
}
}
debugging this function i change in the right way the value of the boolean of each filter, but there is the problem, how can i set an ngIf in my html file with this logic?
component.html
Filter select i have to click on at the start
<div class="col-2 d-flex">
<mat-form-field>
<mat-label>{{ 'supplier.showFilters' | translate }}</mat-label>
<mat-select (selectionChange)="toggleSelected()" formControlName="filter">
<mat-option *ngFor="let filter of filters; let i = index" [value]="filter.name"
>
{{i}} {{filter.name}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
Exemple of filter i would like to let appear selecting his own option in the previous select:
<div class="col-2">
<mat-form-field>
<mat-label>{{ 'supplier.supplierStatus' | translate }}</mat-label>
<mat-select formControlName="supplierStatus">
<mat-option [value]="null">--</mat-option>
<mat-option *ngFor="let option of selectData.supplierStatus" [value]="option.value">
{{ option.display | translate }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
at the start of this 'task' i was thinking about declare a global variable instead of a single boolean to each filter but obviously he toggled off/on every filter
p.s. im sorry for my english skills!

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>

Cascading dropdown Edit is not working in angular?

This is my object:
const ELEMENT_DATA: Element[] = [
{id: 1, name: 'Hydrogen', symbol: 'H'},
{id: 2, name: 'Hydrogen', symbol: 'H1'},
{id: 3, name: 'Helium', symbol: 'He'}
];
which is displayed in datatable with Edit buttons, like so:
When I click Edit (for example I clicked Hydrogen) it should populate with
name: 'Hydrogen', symbol: 'H'.
But now I am getting the Symbol List dropdown empty.
Demo
When I click the Add button, a pop up will come with two dropdowns: Element List and Symbol List. Based on the Element name Symbol List will come.
Now when I click the Edit button in datatable, that should populate that particular row in the popup. How can I do this?
html
<form [formGroup]="addTaskForm" (ngSubmit)="save()" >
<mat-form-field>
<mat-select formControlName="name" placeholder="Element List" (selectionChange)="elementSelectionChange($event)">
<mat-option *ngFor="let element of Elements" [value]="element.name">
{{ element.name }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-select formControlName="symbol" placeholder="Symbol List">
<mat-option *ngFor="let element of selectedElementSymbol" [value]="element.symbol">
{{ element.symbol }}
</mat-option>
</mat-select>
</mat-form-field>
<div mat-dialog-actions>
<button mat-button (click)="onNoClick()">Cancel</button>
<button type="submit" mat-button cdkFocusInitial>Add</button>
</div>
</form>
You shoule update datasource after each value added from the dialog, change your save() function like this:
save() {
const data = this.data.originalform.dataSource.data;
this.addTaskForm.value["id"]=data.length+1
data.push(this.addTaskForm.value);
this.data.originalform.dataSource=new MatTableDataSource<Element>(data);
console.log('working');
console.log(this.addTaskForm.value);
}
And to not forget to add a referer to the parent object originalform from this:
let dialogRef = this.dialog.open(DialogOverviewExampleDialog, {
width: '250px',
data: { element: element,originalform:this }
});
Hope this helps:)
Edit:
By call of this comment, i updated the fiddle in the following to fit the paginating in.
Adding paginator figures as following:
this.data.originalform.dataSource.paginator=this.data.originalform.paginator;
The symbol list is initialized in the method elementSelectionChange, but
you are calling elementSelectionChange($event) only when the Element list selection changes.
<mat-select formControlName="name" placeholder="Element List" (selectionChange)="elementSelectionChange($event)">
One way you can do it is,
elementSelectionChange(event) {
this.loadSymbols(event.value);
}
loadSymbols(name) {
let value = this.Elements.find(e => e.name === name);
this.selectedElementSymbol = this.Symbols.filter(e => e.id === value.id);
console.log(this.selectedElementSymbol);
}
and then call loadSymbols in the constructor
constructor() {
if (data.element) {
this.name = data.element.name;
this.symbol = data.element.symbol;
this.loadSymbols(this.name);
}
}
StackBlitz

Categories