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.
Related
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.
I have an Input field in my angular template-driven form. I want to configure that fields so that it can only take an 11bits number like 01001111100
<input
class="form-control"
id="bitsValue"
[placeholder]="field.templateOptions.placeholder"
pattern="[0-1]{1}"
[(ngModel)]="ABC"
>
How can I do that?
If you were to use reactive forms, create you form for example:
this.myForm = this._sb.fb.group(
{
bitsValue: this._sb.fb.control('', [Validators.required, YourValidatorClass.elevenBitsOnly])
};
export class YourValidatorClass {
static elevenBitsOnly(control: AbstractControl): ValidationErrors | null {
const value = control.value;
//... validate your value meets your 11 bit requirement
return { bitValueReq: 'You must provide value as 11 bits number' };
//... if it doesn't meet the requirement return null
return null;
}
}
Then in your html template:
<div [formGroup]="myForm">
<mat-form-field>
<input matInput type="text" formControlName="bitsValue" />
<mat-error *ngIf="myForm.hasError('bitValueReq'))"> {{ getErrorMessage(myForm.get('bitsValue')) }}</mat-error>
</mat-form-field>
</div>
....component.ts file:
getErrorMessage(control: AbstractControl): string{
const error = control.getError('bitValueReq');
if(error){
return error['bitValueReq'];
}
}
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
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>
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