Data binding <select> element's selected index with Angular - html

Could I please ask what I am doing wrong in the following:
Firstly, the following works fine:
I have the following variables in my .ts component:
public m_array = ["one", "two", "three", "four"];
public m_selectedValueIndex = "two";
and in my html I have:
<select [(ngModel)]="m_selectedValueIndex">
<option *ngFor = 'let num of m_array'>
{{num}}
</option>
</select>
All works fine, and I can see that I have two-way binding on m_selectedValueIndex.
But If I change to the code below things do not work as I expected they would:
.TS code:
public m_array = ["one", "two", "three", "four"];
public m_selectedValueIndex = 2; // THIS IS NOW A NUMBER
html code:
<select [(ngModel)]="m_array[m_selectedValueIndex]"> // THIS IS NOW AN INDEX TO ARRAY
<option *ngFor = 'let num of m_array'>
{{num}}
</option>
</select>
Initially it looks like it's working because the initially selected item is indeed the one with and index of m_selectedValueIndex. But if I use the list box then the values listed actually change.
I may initially have:
one
two
three
four
(where italics indicates that it is selected). This is as I would expect because m_selectedValueIndex = 2.
But if I click on any item (say "four" for example) then the listbox contents change to:
one
two
four
four
i.e. it is replacing item at index m_selectedValueIndex with my selection. Also the value of m_selectedValueIndex remains 2.
Just wanted to see if I could bind by index instead of value.
Thanks for any help.

You need to bind the option value to the array's index using [value]="ndx", (after defining it using let ndx = index within *ngFor)
like the following:
<select [(ngModel)]="m_selectedValueIndex"> // THIS IS NOW AN INDEX TO ARRAY
<option *ngFor="let num of m_array; let ndx = index" [value]="ndx">
{{ num }}
</option>
</select>

Related

Can't display options in select list using *ngFor in Angular 9

I'm having trouble displaying the options in a select list. The HTML code is the following:
<select class="selectpicker" (change) = "searchCountry(selectedCountry)" [(ngModel)] = "selectedCountry" data-live-search="true" title = "Selecciona un país">
<option [ngValue]="object" *ngFor = "let object of countryList" >{{object.Country}}</option>
</select>
What I'm trying to do is to display the property "Country" (which is a string) of the objects inside the countryList array.
The problem is that there are no options displaying, the select list is empty.
I'm sure that the problem is not with countryList because if I run the following code outside the select element, the Country property displays correctly.
<h2>{{countryList[0].Country}}</h2>
I've also tried replacing countryList with an array like the following, and it displays correctly, so I'm not sure that the problem is with the select list.
countryList: Country[] = ["Argentina", "Chile", "Ecuador];
Can it be related to the length of the countryList array? It has 186 elements.
Please try this:
<option *ngFor="let country of countryList" value="{{country}}">{{country}}</option>
in case that countryList is
countryList: Country[] = ["Argentina", "Chile", "Ecuador];
As you have shown countryList is array of strings so you can't use it like object.Country simply use object
use like below
<select [(ngModel)]="selectedCountry" (change) = "searchCountry(selectedCountry)">
<option [value]="object" *ngFor="let object of countryList">{{object}}</option>
</select>
Working example
https://stackblitz.com/edit/angular-select-example-v6rndj?embed=1&file=app/app.component.html
Thanks for the answers, I've partially solved the issue.
The code was ok, the problem was the class of the select box in the HTML code. I deleted 'class="selectpicker"' and the select box started showing all the options. This class is from bootstrap-select, maybe it doesn´t support this kind of clauses.
So the code is like this:
<select (change) = "searchCountry(selectedCountry)" [(ngModel)] = "selectedCountry" title = "Selecciona un país">
<option *ngFor = "let countryName of countryList" >{{countryName.Country}}</option>
</select>
I forgot to mention that countryList's elements are delivered by an HTTP GET method, so replacing it with a string array was not an option. The issue could've been generated by the delay in the HTTP response.
Thanks again.

How to set the first item in a select drop down using ngFor in Angular

I have this drop down below and it has all the countries in it, but doesn't display the first value ('United States'). How can I get the first item to be the selected one?
Is it possible to have a conditional statement that sets 'selected' if index = 0? I know two bindings aren't possible, but I'm looking at other alternatives.
<div class="form-group">
<select id="country" class="form-control" formControlName="countryList">
<option *ngFor="let country of countryList;" value={{country}}>
{{country}}
</option>
</select>
</div>
and below is what I see in the page. No item is initially selected. It's blank until I select something!
Update - I'm trying this below, but it doesn't seem to work either.
[value]="country"
[selected]="country == 'United States' ? true : null"
CountryList looks like this
export class Countries {
countryList: string[] = ['United States', 'Afghanistan', 'Albania'];
CountryList() {
return this.countryList;
}
}
// to initialize it, in my component I do this
countryList: string[] = new Countries().countryList;
Assign initial value to the formControl which you want from the countryList.
ex:-
controlModel.controls['countryList'].setValue('United States');

Angular: How to set a default selection on a select input

What I'm using
angular
firebase
Currently, a standard HTML select component
What I'm trying to achieve
When a user is filling out some details in some inputs, I have a drop down containing a number of options
I want to have a default option selected (not a placeholder, an actual selection)
Question
As I'm looping through an array (ngFor), how do I apply a 'selected' attribute to one of the options? Let's say for example that the array contained 'album 1', 'album 2'and 'album 3'. By default, I want 'album 2' to be automatically selected.
<select #selectedAlbum>
<option *ngFor="let album of albumList" [value]="folder.folder_title">{{album.album.title}}</option>
</select>
You can bind your select element to an ngModel and then on the initialisation of your component set the ngModel to be your desired default value and the option will be selected for you by the two way binding provided by ngModel.
i.e.:
<select #selectedAlbum [(ngModel)]="mySelectedItem">
and in your component:
mySelectedItem: string;
ngOnInit() {
this.mySelectedItem = 'album 2';
}
You can add a selected attribute:
example using a predefined item
<select #selectedAlbum>
<option *ngFor="let album of albumList" [value]="folder.folder_title" [selected]="ablum.ablum.title === 'album 2'">{{album.album.title}}</option>
</select>
example using an index
<select #selectedAlbum>
<option *ngFor="let album of albumList; let i = index;" [value]="folder.folder_title" [selected]="i === 1">{{album.album.title}}</option>
</select>
Note:
This method does not use two-way binding. This is a one-way binding as you currently have implemented. If you'd prefer to use two-way binding (which is much more elegant in general) I'd highly recommend digging deeper into form models.

Setting selected option of select control in an Angular 2 model-driven form

I have researched many similar existing answers on SO and elsewhere, but just can't find the solution to this.
I'm using the model-driven approach in Angular 2 to build my form, which is both an add and edit form. When in edit mode, the values are populated with data retrieved from a service: this aspect is all fine because the simple text inputs all bind correctly.
One of the properties is 'Country' and this is an object as follows:
export class Country {id: number; name: string;}
I want to bind this to a select control which will have the list of countries available, and the one from the model populated when the form loads. I want the value of the binding to be the country object, not just the id.
Here's the html of the select control:
<select class="form-control" id="country" formControlName="country">
<option value="default">--Select a country--</option>
<option *ngFor="let c of countries" [value]="c">{{c.name}} </option>
</select>
And here is where i try to to populate the value from the component class:
(<FormControl>this.personForm.controls['country'])
.setValue(this.person.country, { onlySelf: true });
But there is no selected option when the page loads, even though the console confirms that this.person.country exists and is populated with the correct object.
I can get it working with ids: changing to [value]="c.id" in the view and appending .id in the class, and then it works in that the right option is selected. The problem is that the select no longer emits an object for the country property, just the id. I tried changing [value] to [ngValue] and get the same result. I even added [ngModel]="country" to the select element and that didn't help either.
I'd be grateful for any help.
The issue is most likely that this.person.country is not the same country as in your countries array.
If we want to make them the same we can either explicitly subscribe to the valueChanges of the select control or bind [(ngModel)] to person.country:
subscribe to changes
code
this.countryForm.controls['country'].valueChanges.subscribe(country =>
this.person.country = country;
);
// initialize by finding the correct country object (this will overwrite the person's country object)
this.countryForm.controls['country'].setValue(countries.filter(c => c.id === person.country.id));
template
ngModel bind
We still have to make the objects match (compare strategy that Angular 2 uses which is really what JS uses)
code
this.person.country = this.countries.filter(c => c.id === this.person.country.id)[0];
template
<select class="form-control" id="country" formControlName="country" [(ngModel)]="person.country">
<option value="default">--Select a country--</option>
<option *ngFor="let c of countries" [ngValue]="c">{{c.name}}</option>
</select>
ngModel Plunker: http://plnkr.co/edit/UIS2V5rKh77n4JsjZtii?p=preview
subscription Plunker: http://plnkr.co/edit/yyZ6ol1NPD77nyuzwS2t?p=info

How to set the value of a select element's selected property

I am using webmatrix, razor syntax and cshtml file.
I have an "edit" page for a database record which contains a select box(id="selStatus"). I am trying to set the "selected" value of the select box dynamically, based on the value of the current record being edited.
I have the current value or its index in local var's but i cant seem to assign this value back to the select.
if (currentStatus=="Completed"){
selStatus.options[1].selected=true;
}
RES = error: The name 'selStatus' does not exist in the current context.
I am missing something obvious here but can't seem to get it. Any ideas appreciated. Thanks
If you have a static list of options, for example, for Marital Status, you can keep it more legible (for some of us) like this:
<select>
<option value="Single" #(marStat == "Single" ? "selected" : "")>Single</option>
<option value="Married" #(marStat == "Married" ? "selected" : "")>Married</option>
<option value="Divorced" #(marStat == "Divorced" ? "selected" : "")>Divorced</option>
<option value="Widowed" #(marStat == "Widowed" ? "selected" : "")>Widowed</option>
</select>
What this does is that if your razor variable marStat containing the value that you retrieved from the database matches the string in the condition, it renders "selected" into the HTML.
It's a bit of "brute" style but I believe it's very readable.
in the layout site:
#{
if (!IsPost)
{
PageData["accountType"] = 0; /* default value */
}
}
<html>
<head></head>
<body>
<form action="#Href("~/")" method="post">
<select name="accountType">
<option value="0"#(PageData["accountType"] == 0 ? " selected" : "")>Standard</option>
<option value="1"#(PageData["accountType"] == 1 ? " selected" : "")>Golden</option>
<option value="2"#(PageData["accountType"] == 2 ? " selected" : "")>Ultimate</option>
</select>
</form>
</body>
<html>
and on the other site you can access it with something like
var accountType = Convert.ToInt32(Request["accountType"]);
later set it for your needs with
PageData["accountType"] = (required int value);
In .NET 6:
use asp-for="#selectedValue"
#{
string selectedValue = "en-us"
}
<select name="culture" asp-for="#selectedValue">
<option value="pt-br">Português (Brasil)</option>
<option value="en-us">English (United States)</option>
</select>
At runtime .NET will set the selected attribute tag.
Besides using Javascript you can set the selected item when you create the dropdown.
This will work when you have a dynamically generated dropdown. If your dropdown is static then you need to use javascript.
First create the data that will fill the dropdown:
var selectQ = "SELECT StatusName, StatusID FROM MyStatusTable";
List<SelectListItem> statusdropdownlistdata = new List<SelectListItem>();
bool isSelected = false;
foreach(var item in db.Query(selectQ)){
isSelected = false;
if(item.StatusName == "Completed"){
isSelected = true;
}
statusdropdownlistdata.Add(new SelectList Item
{
Text = item.StatusName,
Value = item.StatusID.ToString(),
Selected = isSelected
});
}
The above will create the data you want to add to your dropdown and select an item that meets criteria. You'll have to modify to work with your specific criteria and logic.
Next, add this to the HTML part of your cshtml:
#Html.DropDownList("StatusTypes", statusdropdownlistdata)
The above will render the dropdown list with an ID="StatusTypes" and your dropdown data with selected item.
Look up Html.DropdownList and you'll probably be able to find other options and ways to do this.
I'm not sure if this code will work, since I'm writing it by memory
Felt it good to add this as well - which is how I did it. You can also pass the value to the ViewBag from with the controller and grab it and make the comparison within the view. See below:
Here in the view I pass the value to to the ViewBag -
ViewBag.degreeLevel = userInfo.educationlevel; (user info is just my object)
Then, I make the comparisons in the view, like below: