web-dev-qa-db-fra.com

Comment puis-je positionner un Angular Dialogue de panneau de matériau relatif à un bouton?

Selon un discussion sur Github , il est impossible de positionner un dialogue standard ( api ), mais les dialogues du panneau ( api ) peuvent être positionnés. 

Une démo simplifiée montre que c'est vrai:

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

Les docs Matériau Angular montrent une méthode permettant un positionnement par rapport à l'élément sur lequel vous avez cliqué (ou tout ce qui est passé). Je suis incapable d'obtenir que cela fonctionne, cependant. 

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

Le fait de passer des valeurs précises pour .top() et .right(), par exemple, permet un positionnement par rapport à la fenêtre d'affichage. Je ne peux pas obtenir de positionnement par rapport à l'élément cliqué, cependant. Comment cela est-il censé fonctionner?

14
isherwood

Je travaille avec Angular depuis plusieurs mois et je trouve toujours que la documentation manque, alors pardonnez-moi la longueur de ce message, qui est ma pseudo-documentation sur le sujet. Mais voici ce que je sais:

J'ai seulement réussi à faire fonctionner l'emplacement du panneau, par rapport à un élément cible, en chaînant la fonction addPanelPosition sur la fonction relativeTo en tant que telle:

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

(dans ce cas, ev est l'objet $ event passé par ng-click)

J'ai pu retrouver les paramètres acceptables pour addPanelPosition et ils sont les suivants:

La position du panneau y n'accepte que les valeurs suivantes: centre | aligner les tops | align-bottoms | ci-dessus | au dessous de

Panel x Position accepte uniquement les valeurs suivantes: centre | align-start | align-end | départ offset | fin offset

Il est intéressant de noter que dans la démo Angular Material, ils utilisent les propriétés this._mdPanel.xPosition.ALIGN_START et this._mdPanel.yPosition.BELOW qui se résolvent simplement en chaînes comme leurs valeurs x et y pour la fonction addPanelPosition. Je suis toujours allé droit avec les valeurs de chaîne. Toutefois, l’utilisation de valeurs de chaîne peut être problématique si le développement de cette fonctionnalité est toujours en mutation et qu’elles modifient les valeurs de chaîne acceptables.

Je signalerai un autre problème que j'ai déjà vu.

Une autre astuce qu’ils utilisent dans la démonstration consiste à spécifier un nom de classe dans la fonction relativeTo au lieu d’un élément cible, puis à placer cette classe sur l’élément cible lui-même. Cette approche peut être utile parce que l'objet $ event de ng-click peut fournir différents éléments cible en fonction de ce qui a été cliqué exactement. Par exemple, cliquer sur le bouton <div> va donner une cible différente de celle de cliquer sur le texte <span> à l'intérieur du bouton. Votre panneau changera donc d’emplacement, à moins que vous ne fournissiez la fonctionnalité supplémentaire.

Codepen

J'ai pris leur démo et je l'ai vraiment réduite à la taille pour me concentrer sur cette question. Vous pouvez voir le codepen mis à jour ici

5
I think I can code

Comme je poste dans un commentaire, ici vous pouvez le voir fonctionner sur un plunker.

Ma solution est très proche du @Je pense que je peux coder réponse. Cependant, dans ma réponse, au lieu d'un menu, un <md-dialog> est affiché lorsque l'utilisateur clique sur le bouton, comme il est demandé dans l'OP.

En plus du plunker de travail avec un dialogue, il n’ya pas grand chose à ajouter au bon @Je pense que je peux coder la réponse. Comme indiqué dans le matériau angulaire md-panel demo , il est essentiel de définir la position du panneau par rapport au bouton. Pour ce faire (comme dans la démo angular-material), nous pouvons utiliser une classe css spécifique (demo-dialog-open-button dans mon exemple) pour rechercher l'élément cible. C'est une chose délicate à mon avis ... mais cela fonctionne bien pour ce cas d'utilisation (c'est aussi bien expliqué dans l'autre réponse).

Code pour référence, voir le plunker pour les détails complets:

html (notez la classe css ajoutée au bouton):

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

JS contrôleur.

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

J'espère que ça aide

1
troig

Les dialogues sont des widgets très simples. Le piégeage se concentre sur la chose la plus compliquée qu'ils font. Cela me fait de la peine que votre problème soit devenu si complexe.

Juste pour énoncer l'évidence, vous avez le contrôle complet sur le positionnement de tout dialogue individuel grâce au nom de classe configuré.

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

De plus, dans votre méthode showDialog, pourquoi ne pas configurer un rappel via une promesse pour la méthode ouverte? Quelque chose comme:

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

Je respecte que vous essayiez d'améliorer la logique du plugin et de faire les choses de la "manière angulaire", mais ces exigences relativement simples ne devraient pas vous causer autant de chagrin.

0
cage rattler