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

15
根据Github上的讨论,无法定位标准对话框(API),但可以定位面板对话框(API)。简化演示表明这是正确的。
var position = this._mdPanel.newPanelPosition().bottom(0).right(0);

Angular Material文档展示了一种允许相对于点击的元素(或传入的任何元素)定位的方法。然而,我无法使其正常工作。

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

通过传递硬编码的值给.top().right(),例如,可以相对于视口定位。但是我无法相对于单击的元素进行定位。这应该如何工作?
3个回答

6
我过去几个月一直在使用Angular Material,但仍然觉得文档不够完善,因此请原谅我在这篇文章中进行了一些伪文档的描述。但是这是我所知道的:
我只能通过将addPanelPosition函数链接到relativeTo函数上来使面板位置相对于目标元素工作,如下所示:
var position = this._mdPanel
  .newPanelPosition()
  .relativeTo(ev.target)
  .addPanelPosition('align-start', 'below') // or other values

在这种情况下,ev是通过ng-click传递的$event对象。
我已经找到了addPanelPosition的可接受参数,它们如下:
引用:
面板y位置仅接受以下值: 中心|对齐顶部|对齐底部|上方|下方
面板x位置仅接受以下值: 中心|对齐开头|对齐结尾|偏移开始|偏移结束
有趣的是,在Angular Material演示中,他们使用this._mdPanel.xPosition.ALIGN_STARTthis._mdPanel.yPosition.BELOW属性,它们只是解析为字符串作为addPanelPosition函数的x和y值。我总是直接使用字符串值。但是,如果这个功能的开发仍在改变可接受的字符串值时,使用字符串值可能会有问题。
我还要指出我见过的另一个问题。
在演示中使用的另一个技巧是在relativeTo函数中指定类名而不是目标元素,然后将该类放置在目标元素本身上。之所以这种方法有帮助,是因为ng-click的$event对象可以根据点击的内容提供不同的目标元素。例如,点击按钮<div>会给出与单击按钮内部的<span>文本不同的目标。如果您没有提供额外的功能来避免这种情况,这将导致面板位置发生变化。

Codepen

我采用了他们的演示,并将其大幅简化,以便专注于此问题。您可以在此处查看更新后的codepen代码。


1

如我在评论中发布的,这里你可以在plunker上看到它的工作原理。

我的解决方案非常接近于@I think I can code的答案。但是,在我的答案中,当单击按钮时,显示一个<md-dialog>,因为OP要求这样做。

除了带有对话框的工作plunker外,没有太多需要添加到良好的@I think I can code答案中。正如在angular-material md-panel演示中所示,关键在于将面板的位置相对于按钮设置。为了做到这一点(就像在angular-material演示中一样),我们可以使用特定的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);

希望有所帮助。

0

对话框是非常简单的小部件。 捕获焦点是它们执行的最复杂的事情之一。 你的问题演变成了如此复杂,这让我感到痛心。

显而易见的是,通过配置类名,您可以完全控制定位任何单个对话框。

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

此外,在您的showDialog方法中,为什么不通过Promise设置一个回调来调用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方式”进行操作,但这些相对简单的要求不应该给你带来这么多困扰。


我同意,但我担心固定的CSS定位不是一个理想的解决方案。我所了解的情况表明,定位可以动态发生。 - isherwood

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接