wake-up-neo.com

Wie kann ich eine Angular Material Panel Dialog relativ zu einer Schaltfläche?

Laut einer Diskussion bei Github kann man einen Standarddialog ( api ) nicht positionieren, aber Paneldialoge ( api ) können positioniert werden.

Eine vereinfachte Demo zeigt, dass dies wahr ist:

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

Die Angular Material-Dokumente zeigen eine Methode, mit der die Positionierung relativ zum angeklickten Element (oder was auch immer übergeben wird) möglich ist. Ich bin jedoch nicht in der Lage, dies zum Laufen zu bringen.

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

Die Eingabe von harten Werten für .top() und .right() ermöglicht beispielsweise die Positionierung relativ zum Ansichtsfenster. Ich kann mich jedoch nicht relativ zum angeklickten Element positionieren. Wie soll das gehen?

14
isherwood

Ich habe in den letzten Monaten mit Angular Material gearbeitet und finde immer noch fehlende Dokumentation. Vergessen Sie daher die Länge dieses Beitrags als meine Pseudodokumentation zu diesem Thema. Aber hier ist was ich weiß:

Ich konnte den Panel-Standort nur relativ zu einem Zielelement zum Laufen bringen, indem ich die addPanelPosition-Funktion als solche mit der relativeTo-Funktion verkettete:

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

(In diesem Fall ist ev das durch ng-click übergebene $ event-Objekt.)

Ich konnte die akzeptablen Parameter für addPanelPosition aufspüren und sie sind die folgenden:

Die y-Position des Panels akzeptiert nur die folgenden Werte: Center | ausrichten-tops | Alien-Bottoms | über | unten

Panel x Position akzeptiert nur die folgenden Werte: Center | Align-Start | Ausrichtungsende | Offset-Start | Versatzende

Interessanterweise verwenden sie in der Angular Material-Demo die Eigenschaften this._mdPanel.xPosition.ALIGN_START und this._mdPanel.yPosition.BELOW, die einfach in Strings als ihre x- und y-Werte für die addPanelPosition-Funktion aufgelöst werden. Ich bin immer direkt mit den Stringwerten gegangen. Die Verwendung von String-Werten kann jedoch problematisch sein, wenn die Entwicklung dieses Features noch im Fluss ist und die akzeptablen String-Werte geändert werden.

Ich werde auf ein weiteres Problem aufmerksam machen, das ich gesehen habe.

Ein anderer Trick, den sie in der Demo verwenden, besteht darin, anstelle eines Zielelements einen Klassennamen in der relativeTo-Funktion anzugeben und diese Klasse dann auf dem Zielelement selbst zu platzieren. Der Grund für diesen Ansatz ist, dass das $ event-Objekt von ng-click verschiedene Zielelemente bereitstellen kann, je nachdem, was genau angeklickt wurde. Wenn Sie zum Beispiel auf die Schaltfläche <div> klicken, wird ein anderes Ziel angegeben als beim Klicken auf den Text <span> innerhalb der Schaltfläche. Dies führt dazu, dass Ihr Panel den Standort wechselt, sofern Sie nicht die zusätzlichen Funktionen zur Verfügung stellen.

Codepen

Ich nahm ihre Demo und reduzierte sie wirklich auf die Größe, um mich auf dieses Problem zu konzentrieren. Sie können den aktualisierten Codepen sehen hier

5

Während ich in einem Kommentar poste, kann man sehen, dass hier an einem Plunker arbeitet.

Meine Lösung ist sehr nah an @Ich denke ich kann die Antwort codieren. In meiner Antwort wird jedoch anstelle eines Menüs ein <md-dialog> angezeigt, wenn auf die Schaltfläche geklickt wird, wie im OP angefordert.

Neben dem funktionierenden Plunker mit einem Dialog gibt es nicht viel zum guten @ hinzuzufügen. Ich denke, ich kann die Antwort codieren. Wie im Winkel-Material md-panel-Demo gezeigt, besteht die Taste hier darin, die Position des Panels relativ zur Schaltfläche festzulegen. Um dies zu tun (wie in der Winkelmaterial-Demo), können wir eine bestimmte css-Klasse (in meinem Beispiel demo-dialog-open-button) verwenden, um das Zielelement zu finden. Dies ist meiner Meinung nach eine heikle Sache ... aber es funktioniert gut für diesen Anwendungsfall (es wird auch in der anderen Antwort gut erklärt).

Code als Referenz finden Sie unter Plunker für die vollständigen Details:

html (beachte die zur Schaltfläche hinzugefügte css-Klasse):

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

JSController.

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

Ich hoffe es hilft

1
troig

Dialoge sind sehr einfache Widgets. Beim Fallenfokus geht es um das komplizierteste, was sie tun. Es tut mir leid, dass sich Ihr Thema zu einem so komplexen Thema entwickelt hat.

Um das Offensichtliche zu sagen, haben Sie dank des konfigurierten Klassennamens die vollständige Kontrolle über die Positionierung einzelner Dialoge.

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

Warum richten Sie in Ihrer showDialog-Methode auch einen Rückruf über ein Versprechen für die offene Methode ein? So etwas wie:

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

Ich respektiere, dass Sie versuchen, die Logik des Plugins zu verbessern und Dinge auf "winkelige Weise" zu tun, aber diese relativ einfachen Anforderungen sollten Ihnen nicht so viel Kummer bereiten.

0
cage rattler