Ole Spaarmann
Ole Spaarmann

Reputation: 16749

Angular 2: How to make an option in a select to selected based on a condition?

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

Answers (3)

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

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

Ben Richards
Ben Richards

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

Miroslav Jonas
Miroslav Jonas

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

Related Questions