Angular2 material sidenav - changing rtl/ltr direction dynamically

时间秒杀一切 提交于 2019-12-10 10:46:44

问题


I'm trying to change my layout dynamically according to users' language selection and switch from LTR to RTL on the fly.

I'm using Angular 2 rc6, material 2.0.0-alpha.9-3

It looks like when the page is loaded, it works perfectly with either rtl or ltr. However, when it's changed dynamically from within the app (see plunker), the direction changes but the generated element md-sidenav-content has a miscalculated margin-right and margin-left.

Digging further, I managed to see that the _dir object has an eventEmitter that should watch for on change events of _dir and recalculate the margins

@angular/material/sidenav/sidenav.js:

_dir.dirChange.subscribe(function () { return _this._validateDrawers(); });

But it's never called when changing the direction dynamically. Although, _dir holds the correct value when page is being loaded for the first time, whether its ltr or rtl.

Finally, here's a plunker to demonstrate the behaviour:

http://plnkr.co/edit/o8lXWC?p=preview

I suspect I'm not using _dir correctly but not managed to figure out what's the right way to do it.


回答1:


Take a look at source code Dir directive

@Input('dir') _dir: LayoutDirection = 'ltr';
  • https://github.com/angular/material2/blob/2.0.0-alpha.9/src/lib/core/rtl/dir.ts#L19-L43

As you can see you're changing _dir property instead of dir setter:

set dir(v: LayoutDirection) {
  let old = this._dir;
  this._dir = v;
  if (old != this._dir) {
    this.dirChange.emit(null);
  }
}

So i think your solution should be like:

view

<md-sidenav-layout fullscreen dir="ltr" #root="$implicit">

<select #langSelect (change)="changeLang(langSelect.value, root)">

component

changeLang(lang, root: Dir) {
  this.translate.use(lang);
  root.dir = lang == "fr" ? "rtl" : "ltr";
}

This way you can omit direction: string property on your component.

And one note:

translate: TranslateService; //it's redundant `private translate: TranslateService` does it
direction: string; // omit it

constructor(private translate: TranslateService) {
  this.direction = "ltr"; // omit it
  translate.addLangs(["en", "fr"]);
  translate.setDefaultLang('en');

  let browserLang = translate.getBrowserLang();
  translate.use(browserLang.match(/en|fr/) ? browserLang : 'en');
  this.translate = translate; // it's redundant
}

Here's your Plunker Example

If you think that this is the wrong decision then check this

  • https://github.com/angular/material2/blob/2.0.0-alpha.9/src/demo-app/demo-app/demo-app.html#L42-L48

Hope this will help you!




回答2:


I've been trying to use the "end" and "start" align attribute to solve the problem, but I don't know why it's not possible. I think a possible solution is that you "play" a bit with the NgStyle and the margin-right as I show in the following Plnkr

[ngStyle]="{'margin-right': move}"

example

Hope this could be useful.




回答3:


I am not sure if what I did with angular1 also works with angular 2. That is just adding a CSS:

md-sidenav {
    left: initial;
    right: 0;
}
md-sidenav.md-closed {
    transform: translate3d(100%, 0, 0);
}

To now have it only for those with rtl-direction, adding a class/attribute to the body and then only selecting that, would be sufficient.



来源:https://stackoverflow.com/questions/40147248/angular2-material-sidenav-changing-rtl-ltr-direction-dynamically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!