Select value (not text) of dropdown in Ionic 4

This should be simple & straightforward, but I can’t get it right. I just want to select the VALUE of a dropdown (not the text).

Here’s the dropdown (part of a formControl form)

        <ion-select id="country" [selectedText]="country" cancelText="Cancel" okText="Choose" 
          (ionChange)="setCountry($evt)" formControlName="country">
          <ion-select-option [value]="USA">United States</ion-select-option>
          <ion-select-option [value]="NG">Nigeria</ion-select-option>
        </ion-select>

and here’s the .ts code

constructor(public formBuilder:FormBuilder, private tools:ToolboxService
    , private userSrv: UserService,private authService: AuthenticateService ) 
  {
    this.tools.getLoggedInUser().then((u:UserModel)=>{
      console.log(u);
      this.userAccount=u;
      this.userId=u.id;
      this.mycountry=u.country;
      this.userForm = this.formBuilder.group({
        userId:[u.id],
        name: [u.name, Validators.compose([Validators.required])],
        city: [u.city],
        state: [u.state],
        zip: [u.zip],
        country: [u.country, Validators.compose([Validators.required])],
        email: [u.email, Validators.compose([Validators.required])]
      });
    this.authService.userDetails().getIdToken()
        .then((t)=>{this.userAccount.deviceToken=t; //console.log("usertoken:", t);
      });
    })
   }

//....blah blah blah

  setCountry(evt)
  {
    console.log(evt.target.value); // shows the text (like United States), not the value (USA)
  }

I don’t see where country is defined in your controller, so I don’t know whether this is a bug or not, but it adds to the confusion that is the main issue here, which is that you have too many things fighting for control over this select component.

When you are using reactive forms, the [formControl] or formControlName binding should be the only thing that manages the input component’s value. There should be no ngModel, and no ionChange.

So the good news is that I think that the way that you should be watching changes on this component for stylistic/readability reasons is also going to give the information you are looking for: subscribe to the valueChanges Observable of the country FormControl in your controller.

I would also highly recommend getting rid of every property you reference in your post aside from userForm: userAccount, userId, and mycountry. They will become stale as the user edits things using the form controls, and stale data is one of the biggest sources of hard-to-track bugs in all software, especially in web apps.

Thanks for the feedback. I removed ionChange() and used valueChanges, and it works great. But now, nothing is preselected when the form loads. How do I preselect a value?
The form is for a user to update his/her info, so the user’s country should be preselected when the form loads.

<ion-item>
        <ion-label color="primary" position="floating">Country</ion-label>
        <ion-select cancelText="Cancel" okText="Choose" formControlName="country">
          <ion-select-option value="USA">United States</ion-select-option>
          <ion-select-option value="NG">Nigeria</ion-select-option>
        </ion-select>
      </ion-item>

the .ts

      this.userForm.valueChanges.subscribe((u)=>{
        console.log(u);
      })

Same way you get it out - setValue on the backing FormControl.

Thanks. I added

      this.userForm.controls['countrycode'].setValue(u.countrycode);

but didn’t make a difference. I ended up adding the attribute

 [selectedText]="country"

to the ion-select and it worked.

Now another issue just came up. After saving, I’m getting this error

Error: Uncaught (in promise): ObjectUnsubscribedError: object unsubscribed

I was able to trace it to …

private userSubject:BehaviorSubject<UserModel> = new BehaviorSubject<UserModel | undefined>(undefined);
  
  //... blah blah blah

  getFromLocal(): Observable<UserModel | undefined>
  {
    return this.userSubject.asObservable(); //<--this line
  }

Any suggestions on how to resolve this?

countrycode is not the same as country, so I don’t think you’re accessing the right control. This is partially why I never use formControlName. I put each FormControl into a separate controller property and bind [formControl] instead. That way my IDE and build tools catch typos that can’t get caught when you write controls['countrycode'], and (although this is admittedly very minor on modern hardware) it saves a needless hash table lookup.

I didn’t understand why this existed in the first place, I don’t understand why it’s there now. There must be something else in your actual code that you’re not posting - that shouldn’t even compile, let alone do anything useful. I would not consider this a sustainable state of affairs, but rather a step backwards into spaghetti.

Create a different topic for this issue: it’s unrelated. Incidentally, see this thread for a discussion of why you don’t need asObservable here (or, arguably, anywhere).

1 Like