Search code examples
angulartypescriptionic-frameworkionic2

Ionic 2: How to bind <ion-select> to an option's key?


I'm developing my first Ionic 2 app. I have an <ion-select> with a dynamic option list. That list is represented in my component as a simple dictionary (named stateOptions):

import { Component } from '@angular/core';

@Component({
    templateUrl: './test.html'
})
export class TestPage {

    stateOptions: {
        al: 'Alabama',
        ak: 'Alaska',
        az: 'Arizona',
        ar: 'Arkansas'
    }

    customer: {
        street_address: '123 Sunshine Lane',
        city: 'Phoenix',
        state: 'az'
    }

}

In my view, I would like to configure the <ion-select> so that customer.state gets set to the selected state's key. So, for example, if the user selects "Arkansas" from the dropdown, the value of customer.state would become the string "ar". How can I achieve this?

<ion-item>
    <ion-label>State</ion-label>
    <ion-select [(ngModel)]="customer.state">
        <ion-option *ngFor="???"></ion-option>
    </ion-select>
</ion-item>

<p>Current value of customer.state: {{ customer.state }}</p>

In Angular 1, this is easily accomplished with the ngOptions directive:

<select ng-model="customer.state" ng-options="abbr as name for ( abbr, name ) in stateOptions"></select>

...but it seems like <ion-select> doesn't support this.

Here's one solution I've seen: At init time, convert stateOptions into a format that's easier to work with. In the component, I can do this:

stateOptionsFormatted: Array<Object> = [];

constructor() {
    for (var key in this.stateOptions) {
        this.stateOptionsFormatted.push({
            abbr: key,
            name: this.stateOptions[key]
        });
    }
}

And in the view:

<ion-select [(ngModel)]="customer.state">
    <ion-option *ngFor="let stateOption of stateOptionsFormatted" [value]="stateOption.abbr">{{ stateOption.name }}</ion-option>
</ion-select>

This works, but it's extra boilerplate code to achieve something that's a one-liner in Angular 1.

I also saw a solution which involves a custom pipe to do this conversion in the view - but others said that this would be bad for performance, since it would get run many times as the user interacts with the page.

Is there a better option? There will be many <ion-select>s throughout my app, so I'd prefer something clean and concise if it's available.

Thanks!


Solution

  • You can use Object.keys() as in

    <ion-select [(ngModel)]="customer.state">
        <ion-option *ngFor="let key of stateOptionKeys"></ion-option>
    </ion-select>
    

    And define stateOptionKeys inside the component's ngOnInit() method as,

    this.stateOptionKeys = Object.keys(this.stateOption);
    

    You also have to declare stateOptionKeys as an array-property of the component class.