Avoid IonCheckbox, IonRadio, IonSelect Triggering ionChange On Initial Load

In Vue how do you set v-model or value of IonCheckbox, IonRadio, IonSelect, etc without triggering ionChange upon initial load?

For example for IonSelect the ionChange is triggered when the value is first set.

<ion-select v-model="value" @ionChange="saveValue">
  <ion-select-option :value="option" :key="index" v-for="(option, index) in section.options">{{option}}</ion-select-option>
</ion-select>

And same thing for IonRadioGroup.

<ion-radio-group v-model="value" @ionChange="saveValue">
  <ion-grid>
    <ion-row>
      <ion-col :key="index" v-for="(option, index) in section.options">
        <ion-item>
          <ion-radio slot="start" :value="option"></ion-radio>
          <ion-label>{{option}}</ion-label>
        </ion-item>
      </ion-col>
    </ion-row>
  </ion-grid>
</ion-radio-group>

I only want saveValue called after the user changes the value and not when it’s initially loaded, since I’m posting changes to the API. Is there another event to only get the user changes?

ionChange should not be triggered on initial load. Can you provide the full app in a GitHub repo?

Looks like ionChange is getting fired when v-model or :value is being set. Doesn’t look like the docs show any examples of v-bind to set the initial value.

Can you provide an example how to bind an ion-select or ion-radio-group and then receive event when the value changes?

Using v-model and :value works the same as it does in non-Ionic Vue 3 applications, so your implementation above looks correct. However, depending on how the value ref is set might cause ionChange to fire (I.e. if the value is set asynchronously).

I’m rendering each of the input component types, and the loading the users previously selected values which I guess is why the value is set asynchronously.

However I don’t want to trigger posting the value back the API on initially loading it, only want to trigger a post when the value is changed by the user. I also want each input to save independently since there is no Save button at the bottom of the page.

Is there another event I can use instead of ionChange? Or perhaps work directly with the underlying element events like input? Or is ionInput event still available?

Basically how do I bind an input to a value and also receive events when the user changes the value?

not certain what you are trying to accomplish here? If the value is the same as the initial value then dont save it? Also not sure why you would want to make multiple api calls on the page… what if the user wants to cancel the action? Not sure this is a user experience that most people would expect…

Hi @aaronksaunders, the page can have several inputs like radios, checkboxes, inputs etc, and upon changing any of those values, that single answer value is posted and saved to the API.

So values are saved inline without the user needing to click a Save button at the bottom of the page. Just an example, the textarea in this forum does auto-saving as the input value is changed, very similar in my app.

Essentially I need to load an initial value asynchronously, and then trigger saving when the user changes the value. However the problem with ionChange is that it’s triggers for both user changes and programatic changes.

One possible workaround I found is utilizing ionFocus and ionBlur setting an focussed flag which is checked inside saveValue. So potentially posting to the API is avoided when value is changed programatically and only triggered when the user changes the value.

<ion-radio-group v-model="value" @ionChange="saveValue">
  <ion-grid>
    <ion-row>
      <ion-col :key="'option-' + index" v-for="(option, index) in section.options">
        <ion-item>
          <ion-radio slot="start" :value="option" @ionFocus="onFocus" @ionBlur="onBlur"></ion-radio>
          <ion-label>{{option}}</ion-label>
        </ion-item>
      </ion-col>
    </ion-row>
  </ion-grid>
</ion-radio-group>
onFocus() {
  this.focussed = true;
},
onBlur() {
  this.focussed = false;
},
async saveValue(event) {
  if (this.focussed) {
    try {
      this.saving = true;
      await this.storeDispatch("saveResponse", {
        value: this.value,
        secret: this.secret
      });
    }
    finally {
      this.saving = false;
    }
  }
}

Looks like this might work for ion-checkbox and ion-radio but not sure about ion-select or ion-datetime controls.