How to disable Option from mat-select based on Condition - html

I two mat-select, in the first one I select the type of Customer Individual or Organizational Customer.
If User selects Ind Customer I show another mat-select.
However, the issue is in second mat-select the dropdown options I want to disable certain input fields. How can I achieve that?
HTML Code to select Type of Customer
<mat-form-field>
<mat-label>Select Customer Type</mat-label>
<mat-select (onSelectionChange)="getCustType($event)">
<mat-option *ngFor="let obj of custType" (click)="getCustType(obj)"
[value]="obj" > {{ obj.viewValue }}</mat-option>
</mat-select>
</mat-form-field>
Typescript code:
custType: any[] = [{ value: 'indCust', viewValue: 'IndividualCustomer' }, { value: 'orgCust', viewValue: 'Organizational Customer' }];
Second Dropdown HTML CODE :
<mat-form-field class="col-sm-3">
<mat-label>Select Option to Edit</mat-label>
<mat-select (onSelectionChange)="getoptiontoedit($event)" >
<mat-option *ngFor="let obj of optiontoeditlist" (click)="getoptiontoedit(obj)" [value]="obj"> {{ obj.viewValue }}</mat-option>
</mat-select>
</mat-form-field>
Typescript Code for Second Dropdown:
optiontoeditlist: any[] = [
{ value: 'address', viewValue: 'Address' },
{ value: 'agentRelationship', viewValue: 'Agent Relationship' },
{ value: 'agreementRelationship', viewValue: 'Agreement Relationship' },
{ value: 'organizationCustomer', viewValue: 'Organization Customer' },
{ value: 'complaint', viewValue: 'Complaint' },
{ value: 'contact', viewValue: 'Contact' },
{ value: 'identification', viewValue: 'Identification' },
{ value: 'individualCustomer', viewValue: 'Individual Customer'}
];
I want to disable/hide individualCustomer option from the second dropdown if a user selects Organization Customer in the first dropdown similarly I want to disable/hide OrganazationalCustomer from the second dropdown if a user selects Individual Customer in the first dropdown.

You can implement a pipe for your second options list like below
#Pipe({ name: 'optfilter' })
export class OptionsFilterPipe implements PipeTransform {
transform(alloptions: any[],firstSelectOpt: any<>) {
return alloptions.filter(option => option.value.indexOf(firstSelectOpt.value)==-1); // or whatever your comparator condition is this just for indication
}
}
Then you can use it like
<mat-option *ngFor="let obj of optiontoeditlist | optFilter: 'selectedFirstOption'"

Related

Angular get value from dynamically generated mat select

I'm using Angular material to make a reactive form that look like this:
Form
With this code I make a dynamically generated mat select and an input, but I don't know how to get the value from all of these.
HTML:
<div *ngFor="let number of [].constructor(cantConsumibles)">
<mat-select placeholder="Selecciona un consumible" class="form-control"
formControlName="consumibles">
<mat-option *ngFor="let consumible of consumibles" [value]="consumible">
{{consumible.CodConsumible}}
</mat-option>
</mat-select>
<input matInput type="number" formControlName="consumibles" placeholder="Cantidad">
</div>
<div align="end">
<button mat-button (click)="agregarConsumible(true)"><mat-icon>add</mat-icon></button>
<button mat-button (click)="agregarConsumible(false)"><mat-icon>remove</mat-icon></button>
</div>
TS:
cantConsumibles: number = 0;
agregarConsumible(flag: boolean): void {
(flag) ? this.cantConsumibles++ : this.cantConsumibles--;
}
Any ideas? Thanks in advance
The select API documents say that we could register a change with #Output() selectionChange: EventEmitter<C> https://material.angular.io/components/select/api
So let's add that method on our select to know, what was selected.
<mat-select placeholder="Favorite food" (selectionChange)="onFoodSelection($event)">
<mat-option *ngFor="let food of foods" [value]="food.value">
{{ food.viewValue }}
</mat-option>
</mat-select>
We then console.log the event value but also save the event value to a variable for later use.
#Component({
selector: 'material-app',
templateUrl: 'app.component.html'
})
export class AppComponent {
output: any;
foods = [
{value: 'product10', viewValue: 'Steak'},
{value: 'product20', viewValue: 'Pizza'},
{value: 'product30', viewValue: 'Tacos'},
{value: 'product40', viewValue: 'Lasagne'},
];
onFoodSelection(event:any) {
this.output = event.value;
console.log(event.value)
}
}
Follow same principal on other elemens (select, input, checkbox etc.) getting the event on change in template and doing something with in in typescript code part.
Here is a small example for you: https://stackblitz.com/edit/material-select-change-event-binding-tta13p?file=app%2Fapp.component.ts

Angular material; mat-select display selected color

I have this piece of code to display list of colors that could be chosen by user:
<form>
<h4>mat-select</h4>
<mat-form-field appearance="fill">
<mat-label>Favorite Color</mat-label>
<mat-select [(ngModel)]="selectedValue" name="food">
<mat-option *ngFor="let color of allColors" [value]="'#' + color.value">
<!-- {{color.label}} -->
<span class="color-span" [ngStyle]="{ 'background-color': '#' + color.value }"></span>
</mat-option>
</mat-select>
</mat-form-field>
</form>
import {Component} from '#angular/core';
/**
* #title Select in a form
*/
#Component({
selector: 'select-form-example',
templateUrl: 'select-form-example.html',
})
export class SelectFormExample {
public allColors: any[] = [
{label: 'FFFFFF', value: 'FFFFFF'},
{label: '000000', value: '000000'},
{label: '603813', value: '603813'},
{label: 'FF0000', value: 'FF0000'},
{label: '2E3192', value: '2E3192'},
{label: '006837', value: 'FFD400'},
{label: 'F15A24', value: 'F15A24'},
{label: 'CCCCCC', value: 'CCCCCC'},
{label: 'DBC0B5', value: 'DBC0B5'},
{label: 'FAB49B', value: 'FAB49B'},
{label: '87B2C7', value: '87B2C7'},
{label: 'ACD58A', value: 'ACD58A'},
{label: 'FFF9AE', value: 'FFF9AE'}
];
}
It works as you see in the image below. But I don't know how to display selected color in the mat-select control.
Demo
If you want to customized the selected value their is a selector which you can use mat-select-trigger. It allows you to customize the trigger that is displayed when the select has a value.
Reference:- https://material.angular.io/components/select/api
You can modify your code like below to show the color when user select the value.
<mat-select [(ngModel)]="selectedValue" name="food">
<mat-select-trigger>
<span [ngStyle]="{ 'background-color': selectedValue }"/>
</mat-select-trigger>
<mat-option *ngFor="let color of allColors" [value]="'#' + color.value">
<!-- {{color.label}} -->
<span class="color-span" [ngStyle]="{ 'background-color': '#' + color.value }"/>
</mat-option>
</mat-select>
Demo
mat-select sets the value and displays the label of the mat-option you select, however, it will only show the text from that selection, since you are not showing any text in your labels, nothing is displayed when you select one of the options.
You can add the label for your color in the mat-option elements and then, once you select something, that text will appear in the mat-select element. If you want a visual representation of the color - you can show the value outside of the mat-select element (maybe to the right?).
You can also consider changing the label on your array from the hex value to the name of the color - e.g. {label: 'FFFFFF', value: 'FFFFFF'}, to {label: 'White', value: 'FFFFFF'},
Here is a snippet which shows a suggestion:
<mat-select [(ngModel)]="selectedValue" name="food">
<mat-option *ngFor="let color of allColors" [value]="'#' + color.value">
<!-- {{color.label}} -->
<span class="color-span" [ngStyle]="{ 'background-color': '#' + color.value }"></span>
{{ color.label }}
</mat-option>
</mat-select>

FormControl valueChanges not firing

What might be wrong with this code? I can't see that valueChanges is getting fired.
ngOnInit() {
this.tagsSubscription = this.service.tags$.subscribe(...);
this.createForm();
this.service.getSupportedTags(new TagId('sometag'));
this.languageSelectorForm.get('tagsFilterCtrl').valueChanges
.pipe(takeUntil(this._onDestroy))
.subscribe(() => {
console.log("received value chnage from filter control ");// I don't see the print and the mat-select object's value is `object Object`
this.filterTags();
});
}
createForm() {
this.languageSelectorForm = this.fb.group({
tags: [null, Validators.required],
tagsFilterCtrl:[null] //filter input shows here
});
}
The filter control is being used as
<div id="mat-select-div">
<mat-select id="language-selector" placeholder="Tags" class="selectpicker" formControlName="tags" [ngClass]="validateField(languageSelectorForm,'tags')" #singleSelect>
<mat-option *ngIf="newSearch">Please select</mat-option>
<mat-option>
<ngx-mat-select-search formControlName="tagsFilterCtrl"></ngx-mat-select-search>
</mat-option>
<mat-option *ngFor="let tag of filteredTags | async" [value]="tag">{{tag.subject}}</mat-option>
</mat-select>
</div>
The problem was not with valuechanges. There was some other logic error. However, it is strange that I don't see the print in the valueChanges observable.

How to bind select options to a JSON object using Angular?

I am attempting to build a web application that has a dropdown menu of industries.
This is what my current list looks like:
<mat-select placeholder="Industry" [(ngModel)]="selectedIndustry" >
<mat-option [value]="0">None</mat-option>
<mat-option [value]="1">Aerospace</mat-option>
<mat-option [value]="2">Banking</mat-option>
<mat-option [value]="3">Chemicals</mat-option>
<mat-option [value]="4">Defence</mat-option>
<mat-option [value]="5">Education</mat-option>
<mat-option [value]="6">Finacne</mat-option>
<mat-option [value]="7">Gaming</mat-option>
<mat-option [value]="8">Government</mat-option>
<mat-option [value]="9">Healthcare</mat-option>
<mat-option [value]="10">Insurance</mat-option>
<mat-option [value]="11">Media</mat-option>
<mat-option [value]="12">Mining</mat-option>
<mat-option [value]="13">Resources</mat-option>
<mat-option [value]="14">Retail</mat-option>
<mat-option [value]="15">Telecommunications</mat-option>
<mat-option [value]="16">Utilities</mat-option>
</mat-select>
<button mat-button (click)="loadJSON()">Create</button>
I also have a typescript file of JSON objects that I would like to connect to this list. This is the contents of the typescript file:
export class Industry {
id: Number;
name: String;
industry = [
{id: 1, name: "Aerospace"},
{id: 2, name: "Banking"},
{id: 3, name: "CapitalMarkets"},
{id: 4, name: "Chemicals"},
{id: 5, name: "Defence"},
{id: 6, name: "Education"},
{id: 7, name: "Gaming"},
{id: 8, name: "Government"},
{id: 9, name: "Healthcare"},
{id: 10, name: "Insurance"},
{id: 11, name: "Media"},
{id: 12, name: "Mining"},
{id: 13, name: "Resources"},
{id: 14, name: "Retail"},
{id: 15, name: "Telecommunications"},
{id: 16, name: "Utilities"}
]
}
Currently the dropdown list functions but like expected but when I clike the 'create button' . nothing happens. I cant figure out how to bind each of the dropdown option to the corresponding JSON object. I have seen the use of this below, which I have tried but I cant get it to work for me:
<mat-option *ngFor="let i of Industry.industry" [value]=i>{{i.name}}</mat-option>
Ideally I need to be able to select an object (either linked to the list by value of name or something) and have the json load when create is clicked.
I'm just starting out so any help is appreciated. As . I have a beginner level knowledge could you please explain your answers. Thanks in advance!
Assuming that you have some data that you're going to get from a REST API, you can call the API in the loadJSON method:
import { Component } from "#angular/core";
import { Observable } from "rxjs";
import { DataService } from "./data.service";
/** #title Select with 2-way value binding */
#Component({
selector: "select-value-binding-example",
templateUrl: "select-value-binding-example.html",
styleUrls: ["select-value-binding-example.css"]
})
export class SelectValueBindingExample {
selectedIndustry;
industries = [
{ id: 1, name: "Aerospace" },
...
];
data$: Observable<Array<any>>;
constructor(private dataService: DataService) {}
loadJSON() {
this.data$ = this.dataService.getDataById(this.selectedIndustry);
}
}
I've created a DataService that has a getDataById method. This takes an id as an argument and then returns an Observable<Array<any>>. I've then assigned it to the data$ property on the Component class.
I can unwrap the data$ property in my Component Template using the async pipe. Something like this:
<mat-form-field>
<mat-label>Select an option</mat-label>
<mat-select placeholder="Industry" [(ngModel)]="selectedIndustry">
<mat-option disabled>None</mat-option>
<mat-option
*ngFor="let industry of industries"
[value]="industry.id">
{{ industry.name }}
</mat-option>
</mat-select>
</mat-form-field>
<button mat-button (click)="loadJSON()">Create</button>
<p>You selected: {{selected}}</p>
<pre *ngIf="(data$ | async) as data">
{{ data | json }}
</pre>
Also, instead of hard-coding every single item in the industries array, I can use the *ngFor structural directive to loop through the items in the array and render the mat-option
Hope this helps and clears your doubts.
Here's a Working Sample StackBlitz for your ref.

Preselecting multiple values for mat-select - Angular 6

I'm trying to preselect multiple options in a mat-select. So far I'm not able to achieve this.
Here is the HTML file:
<mat-dialog-content [formGroup]="form">
<mat-form-field>
<mat-select placeholder="participants" formControlName="participants" multiple>
<mat-option *ngFor="let participant of participants" [value]="participant">{{participant}}</mat-option>
</mat-select>
</mat-form-field>
</mat-dialog-content>
Here is the controller:
export class EventViewModalComponent implements OnInit {
form: FormGroup;
calendarEvent: CalendarEvent;
participants = [];
constructor(private fb: FormBuilder,
private participantService: ParticipantService,
#Inject(MAT_DIALOG_DATA) event: CalendarEvent)
{
this.form = fb.group({
title: [event.title, Validators.required],
location: [event.meta.location, Validators.required],
description: [event.meta.description, Validators.required],
start: [event.start, Validators.required],
end: [event.end, Validators.required],
participants: [this.participants, Validators.required]
});
this.calendarEvent = event;
}
ngOnInit() {
this.participantService.getAll().subscribe(data =>{
for(let i = 0; i < data['length']; i++){
this.participants.push(data[i]['name']);
}
})
}
}
This currently selects all the values per default. Here's a screenshot of how it looks currently:
What I'm trying to achieve is having only Cindy and Jim preselected like this:
How can I achieve this? I've read through several SO questions and wasn't successful. Any help is appreciated
With Angular6+ there is a deprecation warning when you have both a formControl and [(ngModel)]
It looks like you're using ngModel on the same form field as
formControl.
Support for using the ngModel input property and ngModelChange event with
reactive form directives has been deprecated in Angular v6 and will be removed
in Angular v7.
Option 1 using [ngModel] without FormControl
As the first answer suggests, split [ngModel] and (ngModelChange) like this.
<mat-select
[(ngModel)]="selectedFoods"
(ngModelChange)="selectedFoods" name="selectedFoods"
placeholder="Favorite food" multiple>
<mat-option *ngFor="let food of allfoods" [value]="food.value">
{{food.viewValue}}
</mat-option>
</mat-select>
And for the ts.
allfoods: Food[] = [
{value: 'steak-0', viewValue: 'Steak'},
{value: 'pizza-1', viewValue: 'Pizza'},
{value: 'tacos-2', viewValue: 'Tacos'},
{value: 'pasta-3', viewValue: 'Pasta'}
];
selectedFoods = [
'steak-0', 'pasta-3'
];
https://stackblitz.com/edit/angular-mat-select-with-ngmodel?embed=1&file=app/select-overview-example.ts
Option 2 using [formControl] without [ngModel]
<mat-form-field>
<mat-select [formControl]="foodForm" placeholder="Favorite food" multiple>
<mat-option *ngFor="let food of allfoods" [value]="food.value">
{{food.viewValue}}
</mat-option>
</mat-select>
</mat-form-field>
In this case, the selection is initialised in the FormControl's constructor.
allfoods: Food[] = [
{value: 'steak-0', viewValue: 'Steak'},
{value: 'pizza-1', viewValue: 'Pizza'},
{value: 'tacos-2', viewValue: 'Tacos'},
{value: 'pasta-3', viewValue: 'Pasta'}
];
myselectedFoods = ['pasta-3', 'steak-0'];
foodForm: FormControl = new FormControl(this.myselectedFoods);
https://stackblitz.com/edit/angular-mat-select-multi-with-formcontrol
I believe that the easiest way is to use [(ngModel)] directive (or a one-way binding, I'll cover it shortly later) to manipulate the value of mat-select: you can bind a variable, which contains elements you want to preselect, something like this:
<mat-select placeholder="participants" formControlName="participants" multiple [(ngModel)]="selection">
<mat-option *ngFor="let participant of participants" [value]="participant">{{participant}}</mat-option>
</mat-select>
And then you can just filter your initial array of items and get only those, which you want to select by default (it should be stored in selection class property in provided case).
I have created a STACKBLITZ to demonstrate, that it's possible. In this example, I filter items at even indexes, and finally we get "1'st, 3'rd, 5'th, ..." items selected.
Notice, that you can split [(ngModel)] into 2 separate directives if you want to use only a one-way binding: [ngModel] or (ngModelChange). For more info, take a look at angular template syntax guide.