Ion-select with dynamic options

Hi guys, I’m diving in head first into ionic 2 and I’m stumped on something that is probably very simple.

I am using ngFor to dynamically add options to a select component like this:

<ion-select [(ngModel)]="zone.kind">
     <ion-option *ngFor="#key of keys" value="{{key}}">{{values[key]}}</ion-option>
</ion-select>

this code works great. But I want it to show as selected for the zone.kind value. I thought i might need to add some logic like <ion-option checked="{{key == zone.kind}}"></ion-option>. But no dice.

What’s the right way to show the selected option with dynamic options shown?

3 Likes

I haven’t used Ionic 2 yet, but would you not just be able to use:
{{values[key].subvalue}}
Sorry if I’m completely off. I haven’t found time to dive into it myself…

Something like this:

<ion-select> <ion-option *ngFor="#zone of zones">{{zone.kind}}</ion-option> </ion-select>

This works for me:

<ion-item>
    <ion-label>Name(s)</ion-label>
    <ion-select [(ngModel)]="data.person" multiple>
      <ion-option *ngFor="#name of namesList" [value] = "name.shortName" [checked]="false">{{name.shortName}}</ion-option>
    </ion-select>
  </ion-item>
8 Likes

That does not work for me. What I am trying to do is to get the select box to show an existing value as selected before the user chooses one. Does your code do that?

2 Likes

Try using checked=“true” in your ion-option element

Sorry, I think i’ve done a poor job explaining myself. I am trying to set the checked value of ion-option based on a variable like this:

But it doesn’t work

3 Likes

Could you try using [checked]="(key == zone.kind)"?

1 Like

Without knowing what the values of modeKeys, zone, and modes are, it should work to select the proper key without needing to use checked at all. For example:

<ion-item>
  <ion-label>Watering Mode</ion-label>
  <ion-select [(ngModel)]="zone.kind">
    <ion-option *ngFor="#key of modeKeys">{{key}}</ion-option>
  </ion-select>
</ion-item>

and in the JS/TS:

  this.zone = {
    kind: 'key2'
  }
  this.modeKeys = [
    'key1',
    'key2',
    'key3',
    'key4',
  ]

Results in this:

image

9 Likes

thank you for your example brandyshea!! I discovered the problem. If the value of key is a number instead of a string, it does not work. This may be a legitimate bug in ionic. In your examlpe if you change this:


this.zone = {
    kind: 1
  }
  this.modeKeys = [
    1,
    2,
    3,
    4,
  ]

it does not work. very interesting…

1 Like

Could you create an issue on this and we will look into it? :slightly_smiling:

http://ionicframework.com/submit-issue/

1 Like

Hey, can you try

<ion-select [(ngModel)]="zone.kind">
     <ion-option *ngFor="#key of keys" [value]="key">{{values[key]}}</ion-option>
</ion-select>

Something like this worked for me (putting [value] )

6 Likes

Hi Brandy, thanks for all your help with so many topics. I’m trying something similar except the values of my options are objects rather than strings. I tried setting locationObject = defaultLocation, but that obviously doesn’t tell ion-select to dive into the defaultLocation object and retrieve defaultLocation.locationName for display. Any ideas here?

  <ion-card>
    <ion-card-header>Select Object</ion-card-header>
    <ion-card-content>
      <ion-list>
        <ion-item>
          <ion-label></ion-label>
          <ion-select [(ngModel)]="locationObject">
            <ion-option *ngFor="#location of locations" [value]="location">{{location.locationName}}</ion-option>
          </ion-select>
        </ion-item>
      </ion-list>
    </ion-card-content>
  </ion-card>

Hey, I don’t understand what you’re trying to achieve. Could you give me more information? What’s working, what’s not? Maybe some code snippets of the JavaScript/TypeScript side of things? Thanks! :slight_smile:

When a user enters the page, I’m setting blastLocation=defaultLocation (defaultLocation being passed as a param), and I want defaultLocation.locationName to be preselected in the ion-select component. Then, users have the option to select from an array of alternative locations, which are also being passed in as a param. These locations are objects, not strings, but they all contain a location.locationName attribute, which is what the ion-select component displays through interpolation {{}}. Everything works fine…except that I can’t get the defaultLocation.locationName to show as pre-selected.

  constructor(nav, navParams) {
    this.nav = nav;
    this.navParams = navParams;
    this.blastLocation = this.navParams.get('pool').defaultLocation;
    this.locations = this.navParams.get('pool').locations; // locations is an array of location objects. Each location object contains a locationName property, amongst others.

…and here’s the actual HTML to match:

  <ion-list>
    <ion-item>
      <ion-icon item-left name="pin"></ion-icon>
      <ion-label></ion-label>
      <ion-select [(ngModel)]="blastLocation">
        <ion-option *ngFor="#location of locations" [value]="location">{{location.locationName}}</ion-option>
      </ion-select>
    </ion-item>
  </ion-list>

It makes sense, right? A user’s default location should be preselected when they enter the page to select a location. This would be easy if it was a just an array of strings, but is proving to be very difficult with an array of objects containing various string attributes. I came up with a messy hack that allows me to display defaultLocation.locationName in the label component, since I can set that manually with <ion-label>{{blastLocation.locationName}}<ion-label>. That way, when the user enters the page, blastLocation.locationName=defaultLocation.locationName, and when the user selects from the list of locations, then blastLocation.locationName=location.locationName. The obvious messiness here is that I then have to hide the area where selected items are normally displayed.

On a completely separate note, how can I set an entire checkbox list = to true by default? For example, upon entering a page, I want every checkbox of the following code to be checked by default.

  <ion-list>
    <ion-item *ngFor="#item of items">
      <ion-checkbox></ion-checkbox> 
      <ion-label>     
        {{item}}
      </ion-label>
    </ion-item>
  </ion-list>

Simply setting checked="true" inside <ion-checkbox></ion-checkbox> does not work.

I know this was a lot, thanks in advance if you have any suggestions :slight_smile:

Matt

@mound Are you sure that the references are the same (test in JSFiddle):

var location1 = { locationName: 'Earth' };
var location2 = { locationName: 'Earth' };
var location3 = location1;
alert('location1 is equal to location2: ' + (location1 === location2)); // false
alert('location1 is equal to location3: ' + (location1 === location3)); // true

I created a simple plunker demo and (if I’m not missing something) it seems to work as expected.

Could you please try to reproduce your problem in plunker and post a link to check it out?

@iignatov, thank you. You were correct in guessing my references were not the same. My solution was to add a “default” boolean to my location objects and find the appropriate one using es6 “find”. Below are two plunks, one showing what I was doing (wrong), and what I did to fix the problem.

What I was doing: plunk1

This works: plunk2

Any insight into my second question (at the bottom of my last post to @brandyshea?) I’d like to set an entire list of checkboxes to true. I want the user to deselect items as opposed to select them.

Thanks again, you guys are awesome and an indispensable resource for someone as green as myself! :seedling:

1 Like

@mound Sorry, I missed that part. I’m not sure how exactly are you setting it, but it seems to work with the standard ways. Check out the updated plunker demo for details.

It’s a bit more complicated. Here’s a plunk to show what I’m working with. Additionally, I am calling these items from the server and would have to set the selected flag to "true" for the entire array upon entering the page.

@mound I guess that the problem is that the selected property of the items is not set to true anywhere except in the click-handler. This means that they won’t be selected until each of them is clicked. I made some updates to your plunker demo and it should work as expected now.

2 Likes

That’s what I was looking for, thank you. I’m curious, why did you include the doSomething() method and use a promise? Why not just call selectAllItems() right out of the gate?