最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How can I position an Angular Material panel dialog relative to a button? - Stack Overflow

programmeradmin5浏览0评论

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

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.

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?

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

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.

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?

Share Improve this question edited Aug 19, 2016 at 14:09 isherwood asked Aug 15, 2016 at 18:54 isherwoodisherwood 61.1k16 gold badges120 silver badges168 bronze badges 0
Add a ment  | 

3 Answers 3

Reset to default 6

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:

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:

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)

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

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

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.

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.

Codepen

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

As I post in a ment, 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.

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

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

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

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

JS controller.

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

Hope it helps

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

Just to state the obvious, you do have plete 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:

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.

发布评论

评论列表(0)

  1. 暂无评论