Change dropdown based on another dropdown in Angular 11? - javascript

I want to change dropdown based on another dropdown.
ts.file
Countries: Array<any> = [
{ name: '1st of the month', states: [ {name: '16th of the month'} ] },
{ name: '2nd of the month', states: [ {name: '17th of the month'} ] },
{ name: '3rd of the month', states: [ {name: '18th of the month'} ] },
]
states: Array<any> = [];
cities: Array<any> = [];
changeCountry(country: any) {
this.states = this.Countries.find(cntry => cntry.name == country.target.value).states;
}
html.file
<mat-form-field>
<mat-select [(ngModel)]="custFirst" name="custFirst" placeholder="Country" (change)="changeCountry($event)">
<mat-option *ngFor="let country of Countries" [value]="country.name" > {{ country.name }}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-select placeholder="State">
<mat-option *ngFor="let state of states" [value]="state.name">{{ state.name }}
</mat-option>
</mat-select>
</mat-form-field>
Now my problem is that, I unable to get the value in second dropdown. Please help me why trigger part is not working.

The change event should be changed to selectionChange. If you want the state to be auto-selected add [(ngModel)] to the state dropdown and update it when the country is changed:
changeCountry(country: any) {
this.states = this.Countries.find(
(cntry) => cntry.name == country.value
).states;
this.sFirst = this.states[0].name;
}
<mat-form-field>
<mat-select [(ngModel)]="custFirst" name="custFirst" placeholder="Country" (selectionChange)="changeCountry($event)">
<mat-option *ngFor="let country of Countries" [value]="country.name" > {{ country.name }}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-select placeholder="State" [(ngModel)]="stateFirst">
<mat-option *ngFor="let state of states" [value]="state.name">{{ state.name }}
</mat-option>
</mat-select>
</mat-form-field>
Working example: https://stackblitz.com/edit/angular-6-stackoverflow-nzvqse?file=src/app/components/stackoverflow-solution/stackoverflow-solution.component.ts

You can handle that with a switch case statements, pass the value of country to the function getStates
country:string = 'Uruguay';
states:string[];
getStates(country: string){
switch(country) {
case '':
this.states = [];
break;
case 'República Dominicana':
this.states = ['', 'Azua', 'Baoruco', 'Barahona', 'Valverde'];
break;
case 'Uruguay':
this.states = ['', 'Artigas', 'Canelones', 'Tacuarembó'];
break;
case 'Venezuela':
this.states = ['', 'Amazonas', 'Apure', 'Yaracuy'];
break;
}
}
this.getCountryData(this.country);
then in view:
<mat-option *ngFor="let state of states" [value]="state.name">{{ state.name }}

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!

Unable to get the Angular Material Auto Complete Values

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

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>

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