Changing Ionic Menu side dynamically

2019-07-05 04:01发布

问题:

I'm trying to change the Ionic 3 Menu side dynamically once user changes the language. For RTL languages menu needs to be on the right, by default it's set on left.

I subscribe to TranslateService from @ngx-translate/core event when the language changes app.components.ts:

this.translate.onLangChange.subscribe((event: LangChangeEvent) => {
  console.info(`Language change to ${event.lang}`);
  this.isRTL = event.lang == 'ar' || event.lang == 'fa';

  if (event.lang == 'ar' || event.lang == 'fa') {
    this.platform.setDir('rtl', true);
    this.menuSide = 'right';
  } else {
    this.platform.setDir('ltr', true);
    this.menuSide = 'left';
  }

  this.platform.setLang(event.lang, true);
});

The code above gets executed successfully when I the language gets changes and all the variables get set as expected (I've written unit tests to be sure and tons of console.logs while the app is running.)

In the template:

<ion-menu [content]="content" [side]="isRTL?'right':'left'" side="{{menuSide}}">
....
</ion-menu>

However, even though the this.menuSide changes in the controller, it won't work as expected.

It seems the side can be changed only before platform.ready(), once the platform.ready() is done, no matter what I set it won’t take any effects.

Edit:

I've tried to use the method in https://stackoverflow.com/a/46417869/636136 but that didn't fix it too.

If I just print menuSide in the template it would have the correct value on the screen, but doesn't have any effect on the menu direction.

I can change the "side" attribute on the menu element manually via browser element inspector and it will change the direction successfully, however using menuSide variable won't do the job.

  • Source code available at https://github.com/SavandBros/gonevis-mobile/blob/master/src/app/app.html

回答1:

I was able to change the side of the ion-menu via HTMLElement directly. I know this is not recommended and it should be handled the way I was trying to make it work in the original question, but that's all I could come up with after trying so many different ways.

I believe the problem I have with ion-menu and its behavior on changing the side is a bug.

Here's what I've changed to get it working.

app.component.ts

export class MyApp {
  #...
  menuSide: string = "left";

  this.translate.onLangChange.subscribe((event: LangChangeEvent) => {
      console.info(`Language change to ${event.lang}`);
      let element: HTMLElement = document.getElementById("lovelyMenu");

      if (event.lang == 'ar' || event.lang == 'fa') {
        this.platform.setDir('rtl', true);
        this.menuSide = 'right';
      } else {
        this.platform.setDir('ltr', true);
        this.menuSide = 'left';
      }

      element.setAttribute("side", this.menuSide);
      this.platform.setLang(event.lang, true);
    });
  }
  ...
}

app.html:

<ion-menu [content]="content" [side]="menuSide" id="lovelyMenu">
....

The commit on Github repo is at github.com/SavandBros/gonevis-mobile/commit/684e4ba4365594b7a7c10216267a16790538d158



回答2:

Use property binding instead of interpolation.

i.e. [side]="menuSide"

<ion-menu [content]="content" [side]="menuSide">
....
</ion-menu>


回答3:

put SIDE key in json file for each lang like for example:

ar.json

"SIDE" : "right",

and en.json

"SIDE" : "left",

and then in html

 <ion-menu [content]="content" side="{{'SIDE' | translate}}"

....



回答4:

alternate solution, simple, smooth and works like a charm

In app.html

  <ion-content class="ttct-app-side-menu-content">
    <ion-list>
      <button menuClose ion-item *ngFor="let page of menuPages" (click)="openPage(page)">
        {{page}}
      </button>
    </ion-list>
  </ion-content>

</ng-template>

<ion-menu *ngIf="language === 'en'" type="overlay" side="right" [content]="content">
  <ng-container *ngTemplateOutlet="ttctSideMenuContent"></ng-container>
</ion-menu>

<ion-menu  *ngIf="language === 'ar'" type="overlay" side="left" [content]="content">
    <ng-container *ngTemplateOutlet="ttctSideMenuContent"></ng-container>
</ion-menu>

In app.component.ts

this.translateService.onLangChange.subscribe((event: LangChangeEvent) => {
      if(this.translateService.currentLang === 'en') {
        platform.setDir('ltr', true);
      } else {
        platform.setDir('rtl', true);
      }
      platform.setLang(this.translateService.currentLang, true);
        });
.
.
.
.
.
  changeLanguage(lang) {
    this.translateService.use(lang);
    this.language = lang;
  }