Can I "force refresh" the contents of a select list?

I’m working on an Ionic 4 / Angular 8 app using ngx-translate for i18n, but I’m having a little bit of difficulty with regards to some select lists in my “Settings” page…

The page in question contains two ion-select elements, one for language selection and another for measurement system (i.e.: “Metric” or “Imperial”). Here are a few code snippets for reference:

<ion-select interface="popover" name="uiLanguage" [(ngModel)]="uiLanguage" (ionChange)="settingChanged($event)">
  <ion-select-option value="system">{{ 'SETTINGS.GENERAL.LANGUAGE.SYSTEM' | translate }}</ion-select-option>
  <ion-select-option value="en">{{ 'SETTINGS.GENERAL.LANGUAGE.EN' | translate }}</ion-select-option>
  <ion-select-option value="de">{{ 'SETTINGS.GENERAL.LANGUAGE.DE' | translate }}</ion-select-option>
</ion-select>
<ion-select interface="popover" name="measurementSystem" [(ngModel)]="measurementSystem" (ionChange)="settingChanged($event)">
  <ion-select-option value="metric">{{ 'SETTINGS.REPORT_CONTENTS.MEASUREMENT_SYSTEM.METRIC' | translate }}</ion-select-option>
  <ion-select-option value="imperial">{{ 'SETTINGS.REPORT_CONTENTS.MEASUREMENT_SYSTEM.IMPERIAL' | translate }}</ion-select-option>
</ion-select>

Note: this settingChanged method is used for numerous other settings, allowing me to persist the setting value internally as it changes. I just hooked in a check here so that if the language option is the one being changed, that I tell my app configuration service to change the language.

settingChanged(event) {
  this.config.saveUserSetting(event.srcElement.name, this[event.srcElement.name]).then((value) => {
    if (event.srcElement.name === 'uiLanguage') {
      this.config.changeLanguage(value);
    }
  });
}

I have no issues changing the UI language, as soon as that changes, the entire UI updates and all strings are then shown in the selected language. The “Interface Language” select list option seems to take a fraction longer to update, which is a bit strange… However, the “Measurement System” select list option only updates after opening that select list.

The actual contents of both select lists don’t change, it’s literally just the translation string in each item’s label that needs to refresh. This feels like there’s something in the the ion-select element that I need to explicitly refresh here, but I can’t work out what or how…

I’ve been searching through Google for others with the same issue, but I’ve only managed to find people trying to change the contents of a select list dynamically, or people who can’t get ngx-translate to work at all (or properly). In my case, it is working correctly, it’s just the ion-select-option elements within ion-select that aren’t refreshing when I want them to.

Does anyone know how I can get around this one…?

One potentially fruitful experiment would be to set the change detection strategy of this component to OnPush, and manually triggering change detection after the UI language is modified.

I’ve never done anything fancy with Angular’s change detection logic, so I’m not actually sure how to make use of ChangeDetectorRef… I’ve been looking through the documentation, tutorials and blog posts now, but I don’t see how to implement it within my app code. :confused:

Setting the component’s ChangeDetectionStrategy to OnPush does affect the page behaviour, but after that I tried calling detectChanges() and markForCheck(), both after changing language as well as inside a continuous loop set up with setInterval (based on something I saw in one of the blog posts).

Everything I’ve tried now either breaks the page completely or presents the same behaviour that I currently have. Am I missing something here?

I did a little bit more digging and I suspect that detectChanges() is actually doing what it’s intended to do, but because the value bound to the second ion-select element’s model hasn’t changed, Angular doesn’t re-render it.

As a very hacky test, I just tried storing the current model value in a temp variable, clearing the live value and then re-assigning the previous inside a setTimeout() with no delay and that causes the value to render in the newly selected language, but unfortunately that causes a rather notable “flash” as it clears and re-renders.

1 Like

This is a bit of a drastic suggestion, but seeing as how it seems to be the quasi-official solution for i18n going forward, maybe it would be worth experimenting with whether the new Angular i18n system gets rid of any of these kinks for you. I have been using this strategy for a bit now, including in Ionic projects.

Thanks for the suggestion, I have been keeping an eye on Angular’s i18n system, haven’t done much with it as yet though…

To be honest, I am starting to like to idea of forcing an app reload when changing language. It’s much closer to the typical behaviour of native apps that way and it makes my life much easier.

I’ve had to move on to other projects at the moment, but I am hoping to get back to this again soon. I’ll come back and update this thread with some details once I’ve worked out how best to handle it. :slight_smile: