如何相对于按钮定位 Angular Material 面板对话框?

How can I position an Angular Material panel dialog relative to a button?

按照discussion at Github one cannot position a standard dialog (api), but panel dialogs (api)即可定位。

一个simplified demo表明这是真的:

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

Angular Material docs 显示了一种允许相对于单击的元素(或传入的任何内容)进行定位的方法。但是,我无法使它正常工作。

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

例如,为 .top().right() 传递硬值,允许相对于视口定位。不过,我无法获得相对于单击元素的定位。这应该如何工作?

过去几个月我一直在使用 Angular Material,但仍然发现缺少文档,所以请原谅这个 post 作为我关于这个问题的伪文档的长度。但这是我所知道的:

我只能通过将 addPanelPosition 函数链接到 relativeTo 函数来使面板位置相对于目标元素起作用:

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

(在本例中,ev是ng-click传递的$event对象)

我能够找到 addPanelPosition 可接受的参数,它们如下:

Panel y position only accepts the following values: center | align-tops | align-bottoms | above | below

Panel x Position only accepts the following values: center | align-start | align-end | offset-start | offset-end

有趣的是,在 Angular Material 演示中,他们使用 this._mdPanel.xPosition.ALIGN_STARTthis._mdPanel.yPosition.BELOW 属性,这些属性简单地解析为字符串作为 addPanelPosition 的 x 和 y 值功能。我总是直接使用字符串值。但是,如果此功能的开发仍在不断变化并且它们更改了可接受的字符串值,则使用字符串值可能会出现问题。

我再指出一个我看到的问题。

他们在演示中使用的另一个技巧是在 relativeTo 函数中指定一个 class 名称而不是目标元素,然后将该 class 放在目标元素本身上。这种方法之所以有用,是因为来自 ng-click 的 $event 对象可以根据所点击的内容提供不同的目标元素。例如,单击按钮 <div> 将提供与单击按钮内的 <span> 文本不同的目标。这将导致您的面板移动位置,除非您提供不这样做的附加功能。

Codepen

我拿了他们的演示并将其真正缩小以专注于这个问题。可以看到更新后的codepenhere

对话框是非常简单的小部件。捕捉焦点是他们所做的最复杂的事情。你的问题演变成这么复杂让我很痛苦。

显而易见的是,由于您配置的 class 名称,您确实可以完全控制定位任何单个对话框。

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

此外,在您的 showDialog 方法中,为什么不通过 open 方法的承诺设置回调?类似于:

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 way",但是这些相对简单的要求不应该让您如此心痛。

正如我在评论中 post,here 你可以看到它在 plunker 上工作。

我的解决方案非常接近@I think I can code answer。但是,在我的回答中,单击按钮时显示的不是菜单,而是 <md-dialog>,正如 OP 中所要求的那样。

除了带有对话框的工作插件之外,没有什么可以添加到好的@I think I can code answer。如angular-materialmd-panel demo所示,这里的关键是设置面板相对于按钮的位置。为此(就像在 angular-material 演示中一样),我们可以使用特定的 css class(在我的示例中为 demo-dialog-open-button)来查找目标元素。在我看来这是一件棘手的事情......但它适用于这个用例(在另一个答案中也有很好的解释)。

参考代码,完整详情见plunker

html(注意添加到按钮的cssclass):

<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);

希望对您有所帮助