[Ionic 5] ion-select Objects as Values not working

Ionic 5, following the documentation for ion-select “Objects as Values”. The example is straight up broken.

Page html

      <ion-select [compareWith]="compareWith">
        <ion-select-option *ngFor="let category of this.categories">{{category.name}}</ion-select-option>
      </ion-select>

Category.ts

export class Category {
    guid: string;
    name: string;

    constructor(guid, name) {
        this.guid = guid;
        this.name = name;
    }
}

Page.ts

export class TaskPage implements OnInit {
    categories: Array<Category>;

  constructor() { }

  ngOnInit() {
    this.categories = new Array<Category>();
    this.categories.push(new Category("1", "Test 1"));
    this.categories.push(new Category("2", "Test 2"));
  }

  compareWithFn = (o1, o2) => {
    return o1 && o2 ? o1.guid === o2.guid : o1 === o2;
  };

  compareWith = this.compareWithFn;
}

First off, I had to change the “compareWith = compareWithFn” to include the “this.”

Second, and more importantly, when I select an option, it doesn’t display what I selected and then if I try to select again, every option is selected.

This is after I selected option “Test 2”

ss

1 Like

Thanks. I haven’t had a new reason to hate on JavaScript for a while.

First off, in case you care, Category can be greatly simplified:

export class Category {
  constructor(public guid: string, public name: string) {}
}

The comparison function can also be accessed directly:

compareWith(o1: Category, o2: Category): boolean {
  return o1 && o2 ? o1.guid === o2.guid : o1 === o2;
}

The only reason to make it an arrow function is if one needs access to other properties of the page controller (which I would generally consider a red flag that something is flawed in the design).

Now for what to do to improve the situation: add [value]="category" to the <ion-select-option>. Without it, the content of the element becomes the value, not the desired object. Which, as you discovered, has some drastic consequences for the poor comparison function, because JavaScript is a horrible, terrible, very bad, no-good language that nobody should have to use for anything.

Your comparison function will happily declare any two strings equal, because:

o1 && o2 => true
o1.guid => undefined
o2.guid => undefined
undefined === undefined => true

…and in the absence of a proper [value] binding for the select option, the resultant values will be the strings “Test 1” and “Test 2”.

Yes, you could modify the comparison function to check that it’s being called with objects, but the point is that app programmers shouldn’t have to do such minutiae.

2 Likes

The code was basically from the example given in the documentation. I didn’t change the structure overly because I wanted to make sure it wasn’t something I did that broke it. I realize what I posted isn’t word for word from the documentation but it’s close enough, and I even took out all my stuff and tried the example as-is. Didn’t work. So somebody might want to run it up the chain that the documentation is wrong. Reflects extremely poorly on the platform as a whole.

Feel free to file a docs bug - probably here. In case it’s not clear, I don’t work for Ionic. I’m a volunteer just like you, so I’m not part of any “chain” to run anything up.

@jfsoftwarellc

I submitted a PR with documentation fixes