2013-10-29 9 views
5

den folgenden Anwendungsfall gegeben:Angular-Ui + D3: Wie kontextuelles Menü (Popover vs modal) zu implementieren?

ich D3js Objekte darzustellen verwenden, die durch AngularJS verwaltet werden. Ich möchte dem D3-Diagramm Interaktivität hinzufügen. Wenn ich auf ein SVG-Element klicke, möchte ich eine Art Popup-Menü haben, um die Objekteigenschaften zu ändern. Diese Eigenschaften werden von AngularJS benötigt, jedoch nicht von D3.

Die D3-Angular-Integration ist von http://bl.ocks.org/biovisualize/5372077 abgeleitet, die einen Verschluss verwendet.

Aktuelle Umsetzung:

Ab heute ich bin mit dem $ modal Service von Winkel-ui Bootstrap das Popup-Menü zu erstellen. Aus functionnality Sicht funktioniert es ziemlich gut: Wenn auf einem svg Elemente klicken, löst D3 ein Ereignis Dieses Ereignis von Angular catched ist, die den $ modal Service Innerhalb des modalen Fensters ruft ändere ich die Objekteigenschaften

Ich bin jedoch nicht mit dem Rendering zufrieden. Ich möchte, dass das Popup-Menü wie ein Popover aussieht. Es sollte in der Nähe des SVG-Elements platziert werden, auf das geklickt wurde.

Soweit ich verstehe, ich habe zwei Möglichkeiten:

  1. weiter den $ modal Service nutzen und sein Aussehen ändern. Welcher Ansatz sollte gewählt werden? Verwenden der Option windowClass?
  2. Beenden Sie den $ modal-Dienst und starten Sie das Hacken der Popover-Anweisung. Das Problem ist, dass ich glaube nicht, dass es möglich ist, eine solche Anweisung zu einem Svg-Element hinzufügen. Die Lösung wäre einen Popover-Service in der Nähe des $ modal Service zu erstellen.

Welche Option sollte gewählt werden? und wie man es implementiert?

EDIT:

Arbeiten Plunker mit einem benutzerdefinierten my-popover Richtlinie: http://plnkr.co/edit/5KYvxi?p=preview

Antwort

9

Es ist möglich, eine Richtlinien hinzufügen, indem d3 generiert Code, nur, was Sie sicherstellen müssen, ist, dass Sie Rufen Sie nach dem Rendern den Dienst $compile für den Inhalt auf.

Für das gegebene Beispiel würde es in etwa so aussehen:

.directive('barChart', function($compile){ // inject $compile 
     var chart = d3.custom.barChart(); 
     return { 
      restrict: 'E', 
      replace: true, 
      template: '<div class="chart"></div>', 
      scope:{ 
       height: '=height', 
       data: '=data', 
       hovered: '&hovered' 
      }, 
      link: function(scope, element, attrs) { 
       var chartEl = d3.select(element[0]); 
       chart.on('customHover', function(d, i){ 
        scope.hovered({args:d}); 
       }); 

       scope.$watch('data', function (newVal, oldVal) { 
        chartEl.datum(newVal).call(chart); 
        $compile(element.contents())(scope); // <-- call to $compile 
       }); 

       scope.$watch('height', function(d, i){ 
        chartEl.call(chart.height(scope.height)); 
        $compile(element.contents())(scope); // <-- call to $compile 
       }) 
      } 
     } 

Und in den d3 ‚s Zeichenfunktion:

 bars.enter().append('rect') 
      .classed('bar', true) 
      .attr('myPopover', 'Text to show') // <-- Adding an attribute here. 
      .attr({x: chartW, 
       width: barW, 
       y: function(d, i) { return y1(d); }, 
       height: function(d, i) { return chartH - y1(d); } 
      }) 
      .on('mouseover', dispatch.customHover); 

Demo

+0

Dank. Ich habe Ihre Lösung mit der Popover-Anweisung von Angular-Ui Bootstrap ausprobiert und konnte feststellen, dass es funktioniert. Hier ist ein Plünderer: http://plnkr.co/edit/ZjNZChVPlBUDWPxGhuEL?p=preview Ein Popover sollte beim Klicken auf eine Leiste geöffnet werden, ist es aber nicht. – apairet

+0

Ich habe viele Änderungen an der Plunker gemacht: feste Schreibweise '' content' zu contents', hinzugefügt 'Bootstrap {js, css}', schrieb Richtlinie 'myPopover' welche verwendet' tooltip' intern.. Die [Positionsberechnung in 'ui.angular'] (https://github.com/angular-ui/bootstrap/blob/master/src/position/position.js#L69) gebrochen wird, wenn [im Vergleich zu der tatsächlichen Implementierung ] (https://github.com/twbs/bootstrap/blob/master/js/tooltip.js#L295). Daher wird "ui.bootstrap" funktionieren, aber die für 'svg' Elemente berechnete Position ist falsch. Ich werde später einen Bugreport einreichen. Demo zur Antwort hinzugefügt. –

+1

eine Pull-Anforderung für das Update Erstellt: https://github.com/angular-ui/bootstrap/pull/1225 –