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

时间:2023-01-27 14:23:37

According to a discussion at Github one cannot position a standard dialog (api), but panel dialogs (api) can be positioned.

根据Github的讨论,无法定位标准对话框(api),但可以定位面板对话框(api)。

A simplified demo shows that this is true:

简化演示显示这是真的:

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

The Angular Material docs show a method that allows positioning relative to the clicked element (or whatever is passed in). I'm unable to get this to work, however.

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

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

Passing in hard values for .top() and .right(), for example, allows positioning relative to the viewport. I can't get positioning relative to the clicked element, though. How is this supposed to work?

例如,传入.top()和.right()的硬值允许相对于视口的定位。但是,我无法获得相对于被点击元素的定位。这应该怎么样?

3 个解决方案

#1


5  

I've been working with Angular Material for the past several months and still find the documentation lacking, so forgive the length of this post as my pseudo documentation on the issue. But here is what I do know:

在过去的几个月里,我一直在使用Angular Material,但仍然发现文档缺乏,所以原谅这篇文章的篇幅是关于这个问题的伪文档。但这就是我所知道的:

I've only been able to get the panel location to work, relative to a target element, by chaining the addPanelPosition function onto the relativeTo function as such:

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

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

(in this case, ev is the $event object passed by ng-click)

(在这种情况下,ev是通过ng-click传递的$ event对象)

I was able to track down the acceptable parameters for addPanelPosition and they are the following:

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

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

面板y位置仅接受以下值:center | align-tops |对齐底部|以上|下面

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

面板x位置仅接受以下值:center | align-start | align-end | offset-start |偏移结束

Interstingly enough, in the Angular Material demo, they use the this._mdPanel.xPosition.ALIGN_START and this._mdPanel.yPosition.BELOW properties which simply resolve to strings as their x and y values for the addPanelPosition function. I've always gone straight with the string values. However, using string values could be problematic if the development of this feature is still in flux and they change the acceptable string values.

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

I'll point out one more issue I've seen.

我会指出我见过的另一个问题。

Another trick they use in the demo is to specify a class name in the relativeTo function instead of a target element, then place that class on the target element itself. The reason this approach can be helpful is because the $event object from ng-click can provide different target elements based on what exactly was clicked. For example, clicking the button <div> is going to give a different target than clicking the <span> text inside the button. This wil cause your panel to shift locations unless you provide the additional functionality not to do so.

他们在演示中使用的另一个技巧是在relativeTo函数中指定一个类名而不是目标元素,然后将该类放在目标元素本身上。这种方法有用的原因是因为ng-click中的$ event对象可以根据点击的内容提供不同的目标元素。例如,单击按钮

将提供与单击按钮内的 文本不同的目标。这将导致您的面板移动位置,除非您提供不这样做的附加功能。

Codepen

Codepen

I took their demo and really cut it down to size to focus on this issue. You can see the updated codepen here

我拿了他们的演示,然后把它缩小到适合这个问题。您可以在此处查看更新的代码集

#2


1  

As I post in a comment, here you can see it working on a plunker.

正如我在评论中发表的那样,你可以在这里看到它正在发挥作用。

My solution is very close the to @I think I can code answer. However, in my answer, instead of a menu, a <md-dialog> is displayed when the button is clicked, as it's requested in the OP.

我的解决方案非常接近@I我想我可以编写答案。但是,在我的回答中,而不是菜单,单击按钮时会显示 ,因为它是在OP中请求的。

Besides the working plunker with a dialog, there is no much to add to the good @I think I can code answer. As it's shown in the angular-material md-panel demo, the key here is to set the position of the panel relative to the button. To do that (like in the angular-material demo), we can use a specific css class (demo-dialog-open-button in my example) to find the target element. this is a tricky thing in my opinion...but it works well for this use case (it's also well explained in the other answer).

除了带有对话框的工作人员,没有太多可以添加到好的@I我想我可以编码答案。正如角度材料md-panel演示中所示,这里的关键是设置面板相对于按钮的位置。为此(我们可以使用角度材质演示),使用特定的css类(在我的示例中为demo-dialog-open-button)来查找目标元素。在我看来,这是一个棘手的事情......但它适用于这个用例(在另一个答案中也有很好的解释)。

Code for reference, see the plunker for the complete details:

代码参考,请参阅plunker以获取完整的详细信息:

html (note the css class added to the button):

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

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

JS controller.

JS控制器。

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

Hope it helps

希望能帮助到你

#3


0  

Dialogs are very simple widgets. Trapping focus is about the most complicated thing they do. It pains me that your issue has evolved into such a complex one.

对话框是非常简单的小部件。陷阱焦点是他们所做的最复杂的事情。我很痛苦你的问题已演变成如此复杂的问题。

Just to state the obvious, you do have complete control over positioning any individual dialog thanks to your configured class name.

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

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

Also, in your showDialog method, why not set up a call-back via a promise for the open method? Something like:

另外,在showDialog方法中,为什么不通过open方法的promise来设置回调?就像是:

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

I respect that you are trying to improve the logic of the plugin and do things the "Angular way", but these relatively simple requirements should not be causing you this much heartache.

我尊重你正试图改进插件的逻辑并做“Angular方式”的事情,但这些相对简单的要求不应该让你这么多心痛。

#1


5  

I've been working with Angular Material for the past several months and still find the documentation lacking, so forgive the length of this post as my pseudo documentation on the issue. But here is what I do know:

在过去的几个月里,我一直在使用Angular Material,但仍然发现文档缺乏,所以原谅这篇文章的篇幅是关于这个问题的伪文档。但这就是我所知道的:

I've only been able to get the panel location to work, relative to a target element, by chaining the addPanelPosition function onto the relativeTo function as such:

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

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

(in this case, ev is the $event object passed by ng-click)

(在这种情况下,ev是通过ng-click传递的$ event对象)

I was able to track down the acceptable parameters for addPanelPosition and they are the following:

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

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

面板y位置仅接受以下值:center | align-tops |对齐底部|以上|下面

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

面板x位置仅接受以下值:center | align-start | align-end | offset-start |偏移结束

Interstingly enough, in the Angular Material demo, they use the this._mdPanel.xPosition.ALIGN_START and this._mdPanel.yPosition.BELOW properties which simply resolve to strings as their x and y values for the addPanelPosition function. I've always gone straight with the string values. However, using string values could be problematic if the development of this feature is still in flux and they change the acceptable string values.

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

I'll point out one more issue I've seen.

我会指出我见过的另一个问题。

Another trick they use in the demo is to specify a class name in the relativeTo function instead of a target element, then place that class on the target element itself. The reason this approach can be helpful is because the $event object from ng-click can provide different target elements based on what exactly was clicked. For example, clicking the button <div> is going to give a different target than clicking the <span> text inside the button. This wil cause your panel to shift locations unless you provide the additional functionality not to do so.

他们在演示中使用的另一个技巧是在relativeTo函数中指定一个类名而不是目标元素,然后将该类放在目标元素本身上。这种方法有用的原因是因为ng-click中的$ event对象可以根据点击的内容提供不同的目标元素。例如,单击按钮

将提供与单击按钮内的 文本不同的目标。这将导致您的面板移动位置,除非您提供不这样做的附加功能。

Codepen

Codepen

I took their demo and really cut it down to size to focus on this issue. You can see the updated codepen here

我拿了他们的演示,然后把它缩小到适合这个问题。您可以在此处查看更新的代码集

#2


1  

As I post in a comment, here you can see it working on a plunker.

正如我在评论中发表的那样,你可以在这里看到它正在发挥作用。

My solution is very close the to @I think I can code answer. However, in my answer, instead of a menu, a <md-dialog> is displayed when the button is clicked, as it's requested in the OP.

我的解决方案非常接近@I我想我可以编写答案。但是,在我的回答中,而不是菜单,单击按钮时会显示 ,因为它是在OP中请求的。

Besides the working plunker with a dialog, there is no much to add to the good @I think I can code answer. As it's shown in the angular-material md-panel demo, the key here is to set the position of the panel relative to the button. To do that (like in the angular-material demo), we can use a specific css class (demo-dialog-open-button in my example) to find the target element. this is a tricky thing in my opinion...but it works well for this use case (it's also well explained in the other answer).

除了带有对话框的工作人员,没有太多可以添加到好的@I我想我可以编码答案。正如角度材料md-panel演示中所示,这里的关键是设置面板相对于按钮的位置。为此(我们可以使用角度材质演示),使用特定的css类(在我的示例中为demo-dialog-open-button)来查找目标元素。在我看来,这是一个棘手的事情......但它适用于这个用例(在另一个答案中也有很好的解释)。

Code for reference, see the plunker for the complete details:

代码参考,请参阅plunker以获取完整的详细信息:

html (note the css class added to the button):

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

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

JS controller.

JS控制器。

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

Hope it helps

希望能帮助到你

#3


0  

Dialogs are very simple widgets. Trapping focus is about the most complicated thing they do. It pains me that your issue has evolved into such a complex one.

对话框是非常简单的小部件。陷阱焦点是他们所做的最复杂的事情。我很痛苦你的问题已演变成如此复杂的问题。

Just to state the obvious, you do have complete control over positioning any individual dialog thanks to your configured class name.

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

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

Also, in your showDialog method, why not set up a call-back via a promise for the open method? Something like:

另外,在showDialog方法中,为什么不通过open方法的promise来设置回调?就像是:

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

I respect that you are trying to improve the logic of the plugin and do things the "Angular way", but these relatively simple requirements should not be causing you this much heartache.

我尊重你正试图改进插件的逻辑并做“Angular方式”的事情,但这些相对简单的要求不应该让你这么多心痛。