Angular2 material sidenav — динамическое изменение направления rtl / ltr

#angular #angular-material2 #right-to-left

#angular #угловой-material2 #справа налево

Вопрос:

Я пытаюсь динамически изменять свой макет в соответствии с выбором языка пользователями и переключаться с LTR на RTL на лету.

Я использую Angular 2 rc6, материал 2.0.0-альфа.9-3

Похоже, что при загрузке страницы она отлично работает либо с rtl, либо с ltr. Однако, когда оно динамически изменяется из приложения (см. plunker), направление меняется, но сгенерированный элемент md-sidenav-content имеет неправильно рассчитанные поля справа и слева.

Копая дальше, мне удалось увидеть, что у объекта _dir есть EventEmitter, который должен отслеживать события изменения _dir и пересчитывать поля

@angular/material/sidenav/sidenav.js:

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

Но это никогда не вызывается при динамическом изменении направления.
Хотя _dir сохраняет правильное значение при загрузке страницы в первый раз, будь то ltr или rtl.

Наконец, вот плунжер для демонстрации поведения:

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

Я подозреваю, что я неправильно использую _dir, но мне не удалось выяснить, как правильно это сделать.

Ответ №1:

Взгляните на директиву исходного кода Dir

 @Input('dir') _dir: LayoutDirection = 'ltr';
  

Как вы можете видеть, вы меняете _dir свойство вместо dir установщика:

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

Поэтому я думаю, что ваше решение должно быть похоже:

Вид

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

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

компонент

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

Таким образом, вы можете опустить direction: string свойство вашего компонента.

И одно замечание:

 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
}
  

Вот ваш пример с плунжером

Если вы считаете, что это неправильное решение, проверьте это

Надеюсь, это поможет вам!

Комментарии:

1. Это выглядит многообещающе! Мне придется немного поиграть с этим, поскольку мое приложение не так упрощено, как plunker. Спасибо за подсказку, я сообщу о результатах.

2. Это сделало свое дело! Большое вам спасибо за то, что направили меня в правильном направлении.

Ответ №2:

Я пытался использовать атрибут выравнивания «end» и «start» для решения проблемы, но я не знаю, почему это невозможно. Я думаю, что возможное решение заключается в том, что вы немного «играете» с ngStyle и правым полем, как я показываю в следующем Plnkr

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

пример

Надеюсь, это может быть полезно.

Комментарии:

1. Дело в том, что это может сработать на поверхности (если у меня не так много контента на моей странице), но основная проблема заключается в том, что сгенерированный элемент md-sidenav-content, содержащий все, по-прежнему имеет неправильное левое поле, поэтому мой контент никогда не сможет охватить всю длину страницы. Смотрите скриншот того, что я имею в виду. ! Скриншот на полях

Ответ №3:

Я не уверен, что то, что я сделал с angular1, также работает с angular 2. Это просто добавление CSS:

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

Чтобы теперь иметь его только для тех, у кого есть rtl-direction, было бы достаточно добавить класс / атрибут в тело, а затем выбрать только это.