Array of Options in ion-options / ion-select not working properly


#1

Hello everyone,

I am having a question related to the use of an array within a data model, that i want to bind to ion-option (in ion-select) with *ngFor. Somehow it does not work. And I do not get an error message.
What do I miss here? Can somebody please give me a hint?

My Data Model looks like this:

profile.ts

export class Profile 
{ name: string;
age: number;
interest: string; 
heroes: ["Batman", "Donald Duck", "Captain America", "Spiderman", "Thor"]
}

in my edit-profile.ts I included this references to the data model:

edit-profile.ts

… 
import { Profile } from './../../models/profile'; 

…

@IonicPage()
@Component({
  selector: 'page-edit-profile',
  templateUrl: 'edit-profile.html',
})

export class EditProfilePage {
profile = {} as Profile;
…

and in my template view I have this line:

edit-profile.html


… 
  

<ion-item>
  <ion-label stacked>Superhero</ion-label>
    <ion-select [(ngModel)]="profile.heroes" name="hero">
      <ion-option *ngFor="let hero of profile.heroes">{{hero}}</ion-option>
    </ion-select> </ion-item>

I do not see what I am doing wrong here…
Can PLEASE somebody give me a solution or at least a little hint what might be wrong here?

THANKS SO MUCH!


#2

OO in JavaScript is largely a mirage. There is absolutely no difference in compiled code between:

profile = {} as Profile;

and:

profile = {};

All the cast does is shut up errors from tsc. So profile has no heroes. One way to avoid getting bit by things like this is to only define classes for things whose lifecycle is managed by Angular DI, such as pages, components, and service providers. Everything else should be an interface instead. The heroes array can move to a property of a HeroService, the page can inject said HeroService and access the list of heroes via it.


#3

@rapropos - Thank you so much for your effort to reply!

If I understand you correctly, the solution is:

  1. Change profile.ts from class to interface
  2. write in profile.ts something like heroes = []; but do not include the variables
  3. generate ionic provider called HeroProvider (or HeroService) and include in this the list of heroes
  4. import the HeroesProvider in account.module.ts as well as in edit-profile.ts and use *ngFor with the HeroesProvider - right?

Is this what you suggest to solve this?

If so, how do I need to change the declaration in edit-profile.ts of
profile = {} as Profile; ?
Can it remain like this or do I somehow need to declare the array for the HeroesProvider? What do I need to write?
Again, thanks a lot!


#4

Add value attribute in ion-option

<ion-item>
  <ion-label stacked>Superhero</ion-label>
    <ion-select [(ngModel)]="profile.heroes" name="hero">
      <ion-option *ngFor="let hero of profile.heroes" [value]="hero">{{hero}}</ion-option>
    </ion-select> </ion-item>

#5

@avishai_peretz_dev Thanks ! Very good point!
I actually had [value]=“hero” in the code already, sorry.
But regardless, it does not show the options in the view…


#6

Yes.

No, no heroes in profile.ts at all.

Yes, and also provide a function to get that list of heroes. If they’re unchanging, that could be as simple as:

allHeroes(): string[] { return this._heroes; }

If they can change, you might want to look into returning an Observable<string[]> instead, to avoid pages getting stale copies of the list of heroes.

More or less, but using *ngFor across the list of heroes that you get from the HeroesProvider.

It can remain as is, because now the list of heroes is coming from somewhere else that is managed by DI.


#7

WOW! Thanks so much. It seems I am a step further, but I get this typical error message that many people report about, but I just do not understand the issue…

I assume that is because I am declaring the variable as heroes = HeroesProvider wrong in edit-profile.ts.

Can you please / maybe tell me how the variable has to be declared in order to pass it into the ion-select / ion-option with

<ion-option *ngFor="let hero of heroes" [value]="hero">{{hero}}</ion-option>

ERROR Error: Uncaught (in promise): Error: Cannot find a differ supporting object ‘function HeroesProvider(http) {
this._heroes = [
‘Batman’,
‘Donald Duck’,
‘Captain America’,
‘Spiderman’,
‘Thor’
];
console.log(‘Hello HeroesProvider Provider’);
}’ of type ‘HeroesProvider’. NgFor only supports binding to Iterables such as Arrays.
Error: Cannot find a differ supporting object ‘function HeroesProvider(http) {
this._heroes = [
‘Batman’,
‘Donald Duck’,
‘Captain America’,
‘Spiderman’,
‘Thor’
];
console.log(‘Hello HeroesProvider Provider’);
}’ of type ‘HeroesProvider’. NgFor only supports binding to Iterables such as Arrays.
at NgForOf.ngOnChanges (vendor.js:38052)
at checkAndUpdateDirectiveInline (vendor.js:9464)
at checkAndUpdateNodeInline (vendor.js:10732)
at checkAndUpdateNode (vendor.js:10694)
at debugCheckAndUpdateNode (vendor.js:11327)
at debugCheckDirectivesFn (vendor.js:11287)
at Object.eval [as updateDirectives] (ng:///EditProfilePageModule/EditProfilePage.ngfactory.js:1729)
at Object.debugUpdateDirectives [as updateDirectives] (vendor.js:11279)
at checkAndUpdateView (vendor.js:10676)
at callViewAction (vendor.js:10917)
at NgForOf.ngOnChanges (vendor.js:38052)
at checkAndUpdateDirectiveInline (vendor.js:9464)
at checkAndUpdateNodeInline (vendor.js:10732)
at checkAndUpdateNode (vendor.js:10694)
at debugCheckAndUpdateNode (vendor.js:11327)
at debugCheckDirectivesFn (vendor.js:11287)
at Object.eval [as updateDirectives] (ng:///EditProfilePageModule/EditProfilePage.ngfactory.js:1729)
at Object.debugUpdateDirectives [as updateDirectives] (vendor.js:11279)
at checkAndUpdateView (vendor.js:10676)
at callViewAction (vendor.js:10917)
at c (polyfills.js:3)
at Object.reject (polyfills.js:3)
at Tab.NavControllerBase._fireError (vendor.js:45968)
at Tab.NavControllerBase._failed (vendor.js:45961)
at vendor.js:46008
at t.invoke (polyfills.js:3)
at Object.onInvoke (vendor.js:4183)
at t.invoke (polyfills.js:3)
at r.run (polyfills.js:3)
at polyfills.js:3
defaultErrorLogger @ vendor.js:2050


#8

I said this in my previous response, but maybe it wasn’t clear. The thing you feed to ngFor must be the list of heroes that you get from the HeroesProvider, not the provider itself.