Reputation: 16749
I'm building a select element in a form from an array of objects. I want one of the options to be selected based on an attribute of the current object (myobject.is_default
).
The basic template code looks like this:
<select formControlName="template">
<option *ngFor="let t of templates" [value]="t.id">{{t.title}}</option>
</select>
I could now set the select option like this:
<select formControlName="template">
<option *ngFor="let t of templates" [value]="t.id" [selected]="t.is_default ? 'selected' : ''">{{t.title}}</option>
</select>
But the problem I'm having is the HTML5 specs which state:
The selected attribute is a boolean attribute.
http://www.w3.org/TR/html5/infrastructure.html#boolean-attributes :
The presence of a boolean attribute on an element represents the true value, and the absence of the attribute represents the false value.
If the attribute is present, its value must either be the empty string or a value that is an ASCII case-insensitive match for the attribute's canonical name, with no leading or trailing whitespace.
The following are valid, equivalent and true:
<option selected />
<option selected="" />
<option selected="selected" />
<option selected="SeLeCtEd" />
The following are invalid:
<option selected="0" />
<option selected="1" />
<option selected="false" />
<option selected="true" />
That means: As soon as the selected attribute is present, the option is selected. So I need a way of not having the selected
in all but one option.
I cannot use ngIf
since it cannot be used together with ngFor
on the same element.
Upvotes: 0
Views: 12963
Reputation: 657058
You can use ngModel
to set what element should be the selected.
<select [(ngModel)]="selectedItem" formControlName="template">
<option *ngFor="let t of templates" [value]="t.id">{{t.title}}</option>
</select>
and in the class
var default = t.templates.find(v => v.is_default);
selectedItem = default && default.length && default[0].id;
Upvotes: 7
Reputation: 3575
If you want to do more complex stuff like get the text of the option, one way is to bind the option list to a complex object.
Create an interface for your object:
export interface Day {
id: number;
text: string
}
Then provide some values for it:
this.days = [
{ id: 1: text: 'Monday'},
{ id: 2: text 'Teusday'}
]
Then use it in your template to create your select list. It's important to use ngValue for the binding of the complex object.
<select [(ngModel)]="configDatas.days" name="days">
<option *ngFor="let day of days" [ngValue]="day">{{day.text}}</option>
</select>
After that, displaying it is simple:
<span>You selected DayId: {{configDatas.days.id}}, Text: {{configDatas.days.text}}</span>
Working example: http://plnkr.co/edit/iSr9dpwa10tHwKM45FAE?p=preview
Upvotes: 0
Reputation: 6627
Since you are using model driven approach, why not just set the value in model during the creation of form control group?
// select first (only?) default template
let defaultTemplate = this.templates.some((template) => template.is_default);
...
// create your form group and pass default template id as value for template select
this.yourForm = this.formBuilder.group({
...
template: [defaultTemplate && defaultTemplate.id],
...
});
Upvotes: 1