问题
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