Ioni c 5 / Angular 8 - проблема приведения из любого в мой пользовательский тип - PullRequest
0 голосов
/ 25 марта 2020

В моем проекте Ioni c 5 у меня есть следующая проблема: я думаю, что у меня есть проблема с кастингом. На мой взгляд, я хочу показывать значки языковых флагов, только если свойство selected-language не соответствует самому языку. Проблема в том, что при первом запуске приложения отображаются все три значка!

У меня есть следующий вид:

<ion-toolbar color="secondary">
    <div class="flags">
      <ion-buttons slot="end" *ngIf="!loading">
        <ion-button *ngIf="selectedLanguage != 'de'" fill="clear" color="dark"
          class="ion-no-padding button-padding flag" (click)="changeLanguage('de')">
          <ion-icon src="../../../assets/flag-icons/de.svg"></ion-icon>
        </ion-button>
        <ion-button *ngIf="selectedLanguage != 'en'" fill="clear" color="dark"
          class="ion-no-padding button-padding flag" (click)="changeLanguage('en')">
          <ion-icon src="../../../assets/flag-icons/en.svg"></ion-icon>
        </ion-button>
        <ion-button *ngIf="selectedLanguage != 'nl'" fill="clear" color="dark"
          class="ion-no-padding button-padding flag" (click)="changeLanguage('nl')">
          <ion-icon src="../../../assets/flag-icons/nl.svg"></ion-icon>
        </ion-button>
      </ion-buttons>
    </div>
  </ion-toolbar>

В службе настроек я использую следующую функцию для получить строку языка из локального хранилища:

async getSetting(type: string) {
    let result;
    try {
      result = await this.storage.get('_setting_' + type);
    } catch (error) {
      console.warn(error);
    }
    return result;
  }

На мой взгляд, я хочу установить выбранный язык:

export type AcceptedLanguage = 'de' | 'en' | 'nl';

В своем компоненте страницы я объявляю и инициализирую selectedLanguage следующим образом :

selectedLanguage: AcceptedLanguage = 'de';

ngOnInit определяется следующим образом:

async ngOnInit() {
    this._loading$ = this.loadingIndicationService.loading$.subscribe(
      (loading) => {
        console.log('loading subscribed in startscreen');
        this.loading = loading;
      }
    );

    this.selectedLanguage = await this.settingsService.getLanguage();

  }

Я уже исправил это, сделав случай переключения вокруг языка следующим образом:

async ngOnInit() {
    this._loading$ = this.loadingIndicationService.loading$.subscribe(
      (loading) => {
        console.log('loading subscribed in startscreen');
        this.loading = loading;
      }
    );

    const lang = await this.settingsService.getLanguage();

    switch (lang) {
      case 'de':
        this.selectedLanguage = 'de';
        break;
      case 'en':
        this.selectedLanguage = 'en';
        break;
      case 'nl':
        this.selectedLanguage = 'nl';
        break;
      default:
        this.selectedLanguage = 'nl';
        break;
    }
  }

Но это не очень хорошее решение! Какое хорошее решение для этого? И почему у нас есть эта проблема? И почему корпус переключателя решает проблему?

Заранее спасибо!

1 Ответ

0 голосов
/ 25 марта 2020

Вот почему в вашем первом случае показываются все 3 * ngIf условные шаблоны, а затем почему переключение «исправляет»:

Ваш начальный код:

async ngOnInit() {
    this._loading$ = this.loadingIndicationService.loading$.subscribe(
      (loading) => {
        console.log('loading subscribed in startscreen');
        this.loading = loading;
      }
    );

    this.selectedLanguage = await this.settingsService.getLanguage();

  }

Ваш код инициализирован «selectedLanguage» со значением по умолчанию («de») изначально, и если не будет попытки чтения из хранилища через Promise - вы увидите только 2 из 3 шаблонов.

Проблема в том, что в приведенном выше коде selectedLanguage получает назначенное разрешение Promise после извлечения данных из хранилища.

И нерешенное ожидание Promise больше не равно значению строки de.

В вашем случае переключения вы используете переменную 'lang' и ждете разрешения Promise в фактическую строку, и только тогда вы присваиваете его свойству selectedLanguage, что предотвращает проблему, поскольку selectedLanguage остается как 'de', пока обещание не будет полностью разрешено.

Вот замечательный пример из MDN , демонстрирующий в вашей консоли, что начальное значение, которое получает переменная, является неразрешенным (в ожидании) Promise:

function resolveAfter2Seconds(x) { 
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

async function f1() {
  var x = await resolveAfter2Seconds(10);
  console.log(x); // initially returns Promise pending, then 10
}

f1();

Просто вставьте это в консоль (devtools в Chrome), чтобы увидеть, что происходит.

Таким образом, ваш исходный код может быть в порядке, даже если вы назначите значение только после того, как оно разрешено таким образом. :

async ngOnInit() {
    this._loading$ = this.loadingIndicationService.loading$.subscribe(
      (loading) => {
        console.log('loading subscribed in startscreen');
        this.loading = loading;
      }
    );

    this.settingsService.getLanguage().then(selectedLanguage => {
        if (selectedLanguage) {
            this.selectedLanguage = selectedLanguage;
        }
    })

  }

ОБНОВЛЕНИЕ:

Я пытался воссоздать ваш вариант использования здесь: https://stackblitz.com/edit/ionic-angular-v5-ab6d6y

Мое подозрение, что в вашем коде может быть что-то еще, что мешает поведению, которое вы хотите. Не стесняйтесь играть.

...