Как я могу поместить диалоговое окно Angular Material panel относительно кнопки?

В соответствии с обсуждением в Github нельзя установить стандартный диалог (api), но диалоговые окна панели (api) могут позиционироваться.

A упрощенная демонстрация показывает, что это верно:

var position = this._mdPanel.newPanelPosition().bottom(0).right(0);

Angular Документы по материалам показывают метод, который позволяет позиционировать относительно элемента с щелчком (или любого другого). Однако я не могу заставить это работать.

var target = el.target;
var position = this._mdPanel.newPanelPosition().relativeTo(target); 

Передача жестких значений для .top() и .right(), например, позволяет позиционировать относительно окна просмотра. Тем не менее, я не могу установить позиционирование относительно элемента с щелчком. Как это должно работать?

Ответы

Ответ 1

Я работаю с Angular Материалом в течение последних нескольких месяцев и все еще не могу найти документацию, поэтому прошу простить длину этого сообщения как мою псевдо-документацию по этой проблеме. Но вот что я знаю:

Мне удалось получить расположение панели по отношению к целевому элементу, привязав функцию addPanelPosition к функции relativeTo как таковой:

var position = this._mdPanel
  .newPanelPosition()
  .relativeTo(ev.target)
  .addPanelPosition('align-start', 'below') // or other values

(в этом случае ev - объект события $, прошедший через ng-click)

Мне удалось найти приемлемые параметры для addPanelPosition, и они следующие:

Позиция панели y принимает только следующие значения:     центр | выравнивающие вершины | выравнивающие днища | выше | ниже

Панель x Позиция принимает только следующие значения:     центр | align-start | выравнивание | офсет-старт | Смещение конца

Довольно интересно, в демонстрации Angular Material они используют свойства this._mdPanel.xPosition.ALIGN_START и this._mdPanel.yPosition.BELOW, которые просто разрешают строки как их значения x и y для функции addPanelPosition. Я всегда прятался со строковыми значениями. Однако использование строковых значений может быть проблематичным, если разработка этой функции все еще находится в движении, и они изменяют допустимые строковые значения.

Я укажу еще одну проблему, которую я видел.

Другим трюком, который они используют в демо, является указание имени класса в функции relativeTo вместо целевого элемента, а затем помещайте этот класс в сам целевой элемент. Причина, по которой этот подход может быть полезен, состоит в том, что объект $event из ng-click может предоставлять разные целевые элементы на основе того, что именно было нажато. Например, нажатие кнопки <div> даст другую цель, чем щелчок на тексте <span> внутри кнопки. Это приведет к тому, что ваша панель сдвинет места, если вы не предоставите дополнительную функциональность, чтобы этого не сделать.

Codepen

Я взял их демо и действительно сократил его до размера, чтобы сосредоточиться на этой проблеме. Вы можете увидеть обновленный код здесь

Ответ 2

Как я размещаю в комментарии, здесь вы можете видеть, как он работает над плункером.

Мое решение очень близко к @Я думаю, что могу ответить на код. Тем не менее, в моем ответе вместо меню отображается <md-dialog>, когда кнопка нажата, как она запросила в OP.

Помимо рабочего плунжера с диалогом, нет ничего, что можно добавить к хорошему @Я думаю, что могу ответить на код. Как показано в демонстрации angular -материала md-panel, здесь нужно установить положение панели относительно кнопки. Чтобы сделать это (например, в демонстрации angular -материал), мы можем использовать определенный класс css (demo-dialog-open-button в моем примере), чтобы найти целевой элемент. это сложная вещь, на мой взгляд... но она хорошо работает для этого случая использования (это также хорошо объяснено в другом ответе).

Код для справки, см. plunker для получения полной информации:

html (обратите внимание, что класс css добавлен к кнопке):

<md-button class="md-primary md-raised demo-dialog-open-button" ng-click="ctrl.showDialog($event)">
   Dialog 
</md-button>

JS.

var position = this._mdPanel.newPanelPosition()
      .relativeTo('.demo-dialog-open-button')
      .addPanelPosition(this._mdPanel.xPosition.ALIGN_START, this._mdPanel.yPosition.BELOW);

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

Ответ 3

Диалоги - очень простые виджеты. Основное внимание уделяется самой сложной вещи. Мне больно, что ваш вопрос превратился в такой сложный процесс.

Просто, чтобы указать на очевидное, у вас есть полный контроль над позиционированием любого отдельного диалога благодаря настроенному имени класса.

.demo-dialog-example {
    top: 20px;
    left: 20px;
}

Также, в вашем методе showDialog, почему бы не настроить обратный вызов через обещание открытого метода? Что-то вроде:

this._mdPanel.open(config).then(function() {
    var dialog = angular.element(document.querySelector('.demo-dialog-example'));
    //Centering, positioning relative to target, or draggable logic goes here
});

Я уважаю, что вы пытаетесь улучшить логику плагина и делать вещи "Angular", но эти относительно простые требования не должны вызывать у вас столько страданий.