I am using Angular 2 (TypeScript).
I want to do something with the new selection, but what I get in onChange() is always the last selection. How can I get the new selection?
<select [(ngModel)]="selectedDevice" (change)="onChange($event)">
<option *ngFor="#i of devices">{{i}}</option>
</select>
onChange($event) {
console.log(this.selectedDevice);
// I want to do something here with the new selectedDevice, but what I
// get here is always the last selection, not the one I just selected.
}
If you don't need two-way data-binding:
<select (change)="onChange($event.target.value)">
<option *ngFor="let i of devices">{{i}}</option>
</select>
onChange(deviceValue) {
console.log(deviceValue);
}
For two-way data-binding, separate the event and property bindings:
<select [ngModel]="selectedDevice" (ngModelChange)="onChange($event)" name="sel2">
<option [value]="i" *ngFor="let i of devices">{{i}}</option>
</select>
export class AppComponent {
devices = 'one two three'.split(' ');
selectedDevice = 'two';
onChange(newValue) {
console.log(newValue);
this.selectedDevice = newValue;
// ... do other stuff here ...
}
If devices is array of objects, bind to ngValue instead of value:
<select [ngModel]="selectedDeviceObj" (ngModelChange)="onChangeObj($event)" name="sel3">
<option [ngValue]="i" *ngFor="let i of deviceObjects">{{i.name}}</option>
</select>
{{selectedDeviceObj | json}}
export class AppComponent {
deviceObjects = [{name: 1}, {name: 2}, {name: 3}];
selectedDeviceObj = this.deviceObjects[1];
onChangeObj(newObj) {
console.log(newObj);
this.selectedDeviceObj = newObj;
// ... do other stuff here ...
}
}
Plunker - does not use <form>
Plunker - uses <form> and uses the new forms API
You can pass the value back into the component by creating a reference variable on the select tag #device and passing it into the change handler onChange($event, device.value) should have the new value
<select [(ng-model)]="selectedDevice" #device (change)="onChange($event, device.value)">
<option *ng-for="#i of devices">{{i}}</option>
</select>
onChange($event, deviceValue) {
console.log(deviceValue);
}
Just use [ngValue] instead of [value]!!
export class Organisation {
description: string;
id: string;
name: string;
}
export class ScheduleComponent implements OnInit {
selectedOrg: Organisation;
orgs: Organisation[] = [];
constructor(private organisationService: OrganisationService) {}
get selectedOrgMod() {
return this.selectedOrg;
}
set selectedOrgMod(value) {
this.selectedOrg = value;
}
}
<div class="form-group">
<label for="organisation">Organisation
<select id="organisation" class="form-control" [(ngModel)]="selectedOrgMod" required>
<option *ngFor="let org of orgs" [ngValue]="org">{{org.name}}</option>
</select>
</label>
</div>
I ran into this problem while doing the Angular 2 forms tutorial (TypeScript version) at https://angular.io/docs/ts/latest/guide/forms.html
The select/option block wasn't allowing the value of the selection to be changed by selecting one of the options.
Doing what Mark Rajcok suggested worked, although I'm wondering if there's something I missed in the original tutorial or if there was an update. In any case, adding
onChange(newVal) {
this.model.power = newVal;
}
to hero-form.component.ts in the HeroFormComponent class
and
(change)="onChange($event.target.value)"
to hero-form.component.html in the <select> element made it work
use selectionChange in angular 6 and above. example
(selectionChange)= onChange($event.value)
I was has same problem and i solved using the below code :
(change)="onChange($event.target.value)"
In Angular 8 you can simply use "selectionChange" like this:
<mat-select [(value)]="selectedData" (selectionChange)="onChange()" >
<mat-option *ngFor="let i of data" [value]="i.ItemID">
{{i.ItemName}}
</mat-option>
</mat-select>
Angular 7/8
As of angular 6,the use of ngModel input property with reactive forms directive have been deprecated and removed altogether in angular 7+. Read official doc here.
Using reactive form approach you can get/set selected data as;
//in your template
<select formControlName="person" (change)="onChange($event)"class="form-control">
<option [value]="null" disabled>Choose person</option>
<option *ngFor="let person of persons" [value]="person">
{{person.name}}
</option>
</select>
//in your ts
onChange($event) {
let person = this.peopleForm.get("person").value
console.log("selected person--->", person);
// this.peopleForm.get("person").setValue(person.id);
}
Another option is to store the object in value as a string:
<select [ngModel]="selectedDevice | json" (ngModelChange)="onChange($event)">
<option [value]="i | json" *ngFor="let i of devices">{{i}}</option>
</select>
component:
onChange(val) {
this.selectedDevice = JSON.parse(val);
}
This was the only way I could get two way binding working to set the select value on page load. This was because my list that populates the select box was not the exact same object as my select was bound to and it needs to be the same object, not just same property values.
If you don't need two-way data-binding:
<select (change)="updateSorting($event)">
<option disabled selected>Sorting</option>
<option value="pointDes">pointDes</option>
<option value="timeDes">timeDes</option>
<option value="timeAsc">timeAsc</option>
<option value="pointAsc">pointAsc</option>
</select>
updateSorting(e: any) {
// console.log((e.target as HTMLSelectElement)?.value); // also work
console.log(e.target.value);
}
<mat-form-field>
<mat-select placeholder="Vacancies" [(ngModel)]="vacanciesSpinnerSelectedItem.code" (ngModelChange)="spinnerClick1($event)"
[ngModelOptions]="{standalone: true}" required>
<mat-option *ngFor="let spinnerValue of vacanciesSpinnerValues" [value]="spinnerValue?.code">{{spinnerValue.description}}</mat-option>
</mat-select>
I used this for angular Material dropdown. works fine
I tried all the suggestions and nothing works for me.
Imagine the situation: you need a 2-way binding and you have a lookup with NUMBER values and you want to fill your SELECT with the values from this lookup and highlight the chosen option.
Using [value] or (ngModelChange) is a no-go, because you won't be able to select the chosen option after user initiated the change: [value] considers everything a string, as to (ngModelChange) - it obviously should not be used when user initiates the change, so it ruins the proper selection. Using [ngModel] guarantees the fixed format of received VALUE as INDEX: VALUE and it's easy to parse it correspondingly, HOWEVER once again - it ruins the selected option.
So we go with [ngValue] (which will take care of proper types), (change) and... [value], which guarantees the handler receives VALUE, not a DISPLAYED VALUE or INDEX: VALUE :) Below is my working clumsy solution:
<select
class="browser-default custom-select"
(change)="onEdit($event.target.value)"
>
<option [value]="">{{
'::Licences:SelectLicence' | abpLocalization
}}</option>
<ng-container *ngIf="licencesLookupData$ | async">
<option
*ngFor="let l of licencesLookupData$ | async"
[ngValue]="l.id"
[value]="l.id"
[selected]="l.id == selected.id"
>
{{ l.id }} {{ l.displayName | defaultValue }}
</option>
</ng-container>
</select>
onEdit(idString: string) {
const id = Number(idString);
if (isNaN(id)) {
this.onAdd();
return;
}
this.licencesLoading = true;
this.licencesService
.getById(id)
.pipe(finalize(() => (this.licencesLoading = false)), takeUntil(this.destroy))
.subscribe((state: Licences.LicenceWithFlatProperties) => {
this.selected = state;
this.buildForm();
this.get();
});
}
latest ionic 3.2.0 have modified (change) to (ionChange)
eg:
HTML
<ion-select (ionChange)="function($event)"> <ion-option>1<ion-option>
</ion-select>
TS
function($event){
// this gives the selected element
console.log($event);
}
In Angular 5 I did with the following way. get the object $event.value instead of $event.target.value
<mat-form-field color="warn">
<mat-select (ngModelChange)="onChangeTown($event)" class="form-width" formControlName="branch" [(ngModel)]="branch" placeholder="Enter branch">
<mat-option *ngFor="let branch of branchs" [value]="branch.value">
{{ branch.name }}
</mat-option>
</mat-select>
</mat-form-field>
onChangeTown(event): void {
const selectedTown = event;
console.log('selectedTown: ', selectedTown);
}
I am displaying a few objects inside a select. But I want to show the user something different after selection than while picking his/her option.
Is that even possible in Angular as it is in WPF?
My select looks like this:
<select class="vstatus-select" [(ngModel)]="rezept.kunde.versichertenstatus1" name="kunde_vstatus1">
<option *ngFor="let vstatus of versichertenstatus1"[ngValue]="vstatus">
{{vstatus.name}} - {{vstatus.kennung}}
</option>
</select>
The Model:
export interface IVersichertenstatus{
name: string;
kennung: string;
}
The Key Problem is, that I want to show "kennung" and "name" while picking an option and only "kennung" afterwards.
I also need ngValue to be the whole object and not just "kennung".
Cheers
You can try this.
<select class="vstatus-select" [(ngModel)]="rezept.kunde.versichertenstatus1" name="kunde_vstatus1">
<option *ngFor="let vstatus of versichertenstatus1"[ngValue]="vstatus">
<span *ngIf="your-condition-to-show-name">{{vstatus.name}} -</span> {{vstatus.kennung}}
</option>
</select>
I hope this help you, regards
Thanks to #Carles Ramos!
I've set two events - and functions which change a boolean. This boolean is used for the *ngIf tag.
<select class="vstatus-select"
[(ngModel)]="rezept.kunde.versichertenstatus1"
name="kunde_vstatus1"
(focus)="vselect_focus(1)"
(change)="vselect_focusout(1)">
<option *ngFor="let vstatus of versichertenstatus1" [ngValue]="vstatus">
<span *ngIf="selectedVersichertenstatus[0]">
{{vstatus.name}} -
</span>
{{vstatus.kennung}}
</option>
</select>
The events look like this:
public selectedVersichertenstatus:boolean[] = [false, false, false];
vselect_focus(selector:number){
this.selectedVersichertenstatus[selector-1] = true;
}
vselect_focusout(selector:number){
this.selectedVersichertenstatus[selector-1] = false;
}
I have a select in angular6 in which option is iterating over an array.
That array has one pipe which dynamically changes array value.
The problem is that when I have one selected value in model and array get changed and that value is not available in that array on which it iterates. Then select by default showing the first element but it should show empty select.
Kindly suggest me the best way to do it.
<select
(change)="handleOfferChange()"
class="alc-form-control"
name="offer"
id="offer"
[(ngModel)]="detailCopy.allowedOffers">
<option
*ngFor="let offer of providerMaster | active: activeOnly"
[ngValue]="[offer.csaid]"
>{{ offer.csaid }}</option
>
</select>
You can manually reset the ngModel, to do this you have to pass ngModel to you pipe as an argument and in your pipe when your array changes, reset the ngModel to empty value (Shown below)
//yourTemplate.html
<select [(ngModel)]="detailCopy.allowedOffers" #mySelectModel="ngModel">
<option *ngFor="let offer of providerMaster | active: activeOnly : mySelectModel" [ngValue]="[offer.csaid]" >{{ offer.csaid }}</option>
</select>
//yourPipe.ts
......
import { NgModel } from '#angular/forms';
transform(arr: any[], mySelectModel: NgModel): any {
if (your logic and conditions) {
mySelectModel.reset();
return arr;
}
}
I am getting content of dropdown list as a Map<number, string>. When I get the map, it is received sorted according to keys in ascending order.
While showing it in html, I am setting pipe keyvalue and provided a function to sort the items in ascending order of values.
Now, I am trying to select first element of this dropdown, but unable to do so.
I have tried jQuery method to select the first element.
I have tried to set ngModel of the select box to first value of the map, but it sets the value to the first value received in the Map which is sorted by key.
My HTML:
<select class="form-control" id="empId" [(ngModel)]="empId" [disabled]="!isEditable">
<option *ngFor="let emp of empNames | keyvalue:descOrder" [value]="emp.key">{{ emp.value }}</option>
</select>
My ts file:
this.commonService.getEmployeeList())
.subscribe((response) => {
this.empNames = response;
this.empId = this.empNames.keys().next().value;
});
data I am sending from server is:
{id:1,name: "Tim"},
{id:6,name: "Martha"},
{id:5,name: "Alex"},
{id:8,name: "Stacy"}
data I am receiving on screen is like:
Alex
Martha
Stacy
Tim
with Tim pre-selected
what I need is Alex should be pre-selected.
Then set the empId before subscribing.
this.empId = 5;
this.commonService.getEmployeeList())
.subscribe((response) => {
this.empNames = response;
});
Of course you might want another logic based on some kind of order. You can never be sure how the data are going to be received.
In this case you need to send the order from your api and filter by order.
Working Demo
<option *ngFor="let emp of empNames | keyvalue:descOrder" [value]="emp.key" [selected]="emp.id === 1">{{ emp.value }}</option>
you can use selected attribute like above
I would highly recommand you to use Angular's reactive forms! And set the select's value to the one you want, when you recieve your data. Don't use ngModel as it is deprecated and should have been removed by Angular 7 (Or will be soon). Check this
The best way to pre select an option is to use ngModel as you tried. Your list is sorted by keys so what you want is not to select the first item, yes it's the first but in other order so or you change the order in code or you search for the item you want to select and stores it to set on model.
I would suggest some changes that should improve the code and fix your problem.
<select class="form-control" id="empId" [(ngModel)]="currentEmployer" [disabled]="!isEditable">
<option *ngFor="let emp of employers$ | async" [value]="emp">{{ emp.value }}</option>
</select>
And order your list in a pipe with the function you prefer.
public currentEmployer: Employer = null;
private sortByNameAscending(e1, e2) {
return e1.name > e2.name ? 1 : 0;
}
this.employers$ = this.commonService.getEmployeeList().pipe(
switchMap(employers => {
const sortedList = employers.sort(this.sortByNameAscending);
if (sortedList.length > 0) {
this.currentEmployer = sortedList[0];
}
return sortedList;
})
);
I'm developing an Angular 2 app with ASP.NET Core 2.0 using the Visual Studio 2017 ASP.NET Angular Web application template.
I have a controller whose method get returns all the legislations that I'm using in my app (they come from an Enum):
[Route("api/[controller]")]
public class LawController : Controller
{
[HttpGet]
public IEnumerable<Models.LawPresentation> Get()
{
List<LawPresentation> laws = new List<LawPresentation>();
// Arrange
byte[] values = (byte[])Enum.GetValues(typeof(LawTypes));
foreach (byte value in values)
{
string enumName = Enum.GetName(typeof(LawTypes), value);
LawPresentation law = new LawPresentation()
{
Value = value,
Name = enumName
};
laws.Add(law);
}
return laws;
}
}
I this is the component that shows all these values in a select:
<p *ngIf="!laws"><em>Loading...</em></p>
Legislaciones:
<select>
<option *ngFor="let l of laws" [ngValue]="l">{{l.name}}</option>
</select>
I don't think that return the default value (a blank option) from the controller is a good idea, so I wondering if I can add something to the html component to add the default option.
Is there any way to add the default option to the select into the html component?
I would do something like this:
<p *ngIf="!laws"><em>Loading...</em></p>
Legislaciones:
<select>
<option></option>
<option *ngFor="let l of laws" [ngValue]="l">{{l.name}}</option>
</select>
You can add a default option as below.
selected property will make option selected at initial.
disable property will restrict option to be selected by user.
You can remove them as per requirement
<p *ngIf="!laws"><em>Loading...</em></p>
Legislaciones:
<select>
<option value="" selected disabled>SELECT</option>
<option *ngFor="let l of laws" [ngValue]="l">{{l.name}}</option>
</select>