2016-05-06 2 views
1

Ich bin neu in AngularJS. Ich habe einige Seiten über das Manipulieren von DOM in Direktive durchsucht, aber die meisten von ihnen manipulieren das DOM der Direktive selbst. Mein Problem ist, das DOM außerhalb der Direktive zu manipulieren.AngularJS manipulieren Eltern DOM in Direktive

In meinem Projekt befindet sich eine Google Map, und auf der Karte befinden sich Markierungen, um Ereignisse anzuzeigen. Was ich tun möchte, ist, dass die Anwendung die detaillierten Informationen des Ereignisses in einem Schieberegler anzeigen soll, wenn auf den Marker geklickt wird. Basierend auf dem folgenden Code besteht die Anforderung, wenn ich auf den Marker klicke, der updateMarkers() in directive auslöst, sollte er den Wert von {{detail}} in HTML ändern. Was ich jetzt mache, versuche "=" zu verwenden, um Direktiven Zugriff auf die Werte in seinem Controllerbereich zu geben, aber dieser Weg funktioniert nicht. Also bitte bieten Sie etwas Hilfe, wenn Sie wissen, danke.

HTML:

<div id="wrapper" > 
    <div class="container-fluid"> 
     <div class="row"> 
      <div class="col-lg-12">     
       <app-map id="map" center="loc" markers="cities" details="details" show-detail="getDetails(directivedata)" on-init="gotoCurrentLocation(directiveData)"> </app-map>     
      </div> 
      <div>**********{{details}}</div> 
     </div> 
    </div> 
</div> 

Teil des Steuerpults:

app.controller("appCtrl", function ($scope, $http) { 
    $scope.nearbyEvent; 
    $scope.details = "something"; //should be changed when click markers in map 
    //code.....} 

Richtlinie:

app.directive("appMap", ['$http', function ($http) { 
    return { 
     restrict: "E", 
     replace: true, 
     template: "<div></div>", 
     scope: { 
      center: "=",  // Center point on the map (e.g. <code>{ latitude: 10, longitude: 10 }</code>). 
      markers: "=",  // Array of map markers (e.g. <code>[{ lat: 10, lon: 10, name: "hello" }]</code>). 
      details: "=",  //used for resend a REST api and store data in here 
      width: "@",   // Map width in pixels. 
      height: "@",  // Map height in pixels. 
      zoom: "@",   // Zoom level (one is totally zoomed out, 25 is very much zoomed in). 
      mapTypeId: "@",  // Type of tile to show on the map (roadmap, satellite, hybrid, terrain). 
      panControl: "@", // Whether to show a pan control on the map. 
      zoomControl: "@", // Whether to show a zoom control on the map. 
      scaleControl: "@", // Whether to show scale control on the map. 
      onInit: "&", 
      showDetail: "&" 
     }, 
     link: function (scope, element, attrs) { 
     //some code..... 
      function updateMarkers() { 
       if (map && scope.markers.length > 0) { 
        window.alert("get me"); 
        // clear old markers 
        if (currentMarkers != null) { 
         for (var i = 0; i < currentMarkers.length; i++) { 

          currentMarkers.setMap(null); 
          window.alert("get here1*****"); 
         } 
        }       
        // create new markers 
        currentMarkers = []; 
        var markers = scope.markers; 

        function makeHappen(thi){ 
         return function(){ 
          scope.details = thi; 
          window.alert("***" + "in directive " + thi); 
         } 
        } 

        for (var i = 1; i < markers.length-1; i++) {      
         var m = markers[i]; 
         if(m.venue == null || m.venue.lat == 0.0) 
          continue; 
         var loc = new google.maps.LatLng(m.venue.lat, m.venue.lon); 
         var eventName = m.description; 
         var mm = new google.maps.Marker({ position: loc, map: map, title: m.name, id: m.id, count: i});             
         mm.addListener('click', makeHappen(eventName), false);      
         currentMarkers.push(mm); 

        } 
       } 
      } 
+0

Ist es Detail oder Details? Ich kann sehen, dass beide benutzt werden. – Saad

+0

Details, Entschuldigung. Ich weiß nicht, warum die Bearbeitung hier falsch ist. Aber in meinem Code werden alle Details im HTML- und JS-Teil genannt. Ich habe es hier schon geändert. Danke – tytan

+0

Um den Wert der Parent-Scope-Variable zu ändern, die durch das Attribut 'details' definiert ist, setze einfach den Wert mit 'scope.details =' new value '; '. – georgeawg

Antwort

1

Verwenden Sie die . Notation, um die Zwei-Wege-Datenbindung ordnungsgemäß zu aktivieren. details ist ein primitiver Typ in Ihrem Controller. Obwohl der Isolate-Bereich in der Direktive auf details zugreifen kann, wenn Sie details in der makeHappen-Funktion etwas zuweisen, erstellt es einen neuen details im isolieren Bereich.

Fügen Sie in diesem Fall anstelle eines primitiven Typs $scope.details in Ihrem Controller ein Objekt ein, z. B .: . Drucken Sie es in Vorlage, d. H .: {{details.msg}}. Ändern Sie details zu details.msg in Ihrer makeHappen Funktion Ihres isolieren Bereichs.

aktualisieren

für meinen Fehler Entschuldigung. Sieht so aus, als müssten Sie scope.details nicht von String zu Objekt ändern. Die untenstehenden Änderungen hätten ausgereicht, damit es funktioniert.

function makeHappen(thi){ 
    return function(){ 
     scope.$apply(function() { 
      scope.details = thi; 
     }) 
    } 
} 

isoliert Umfang, wann immer eine gemeinsame Variable (var Steuerungsbereich mit der Richtlinie Anwendungsbereich gemeinsam) in der Richtlinie Umfang geändert wird, wird die Variable in der Steuerung auch aktualisiert. Es spielt keine Rolle, ob es sich um ein primitives Objekt oder ein Objekt handelt, da zwischen dem Bereich der Richtlinie und dem Bereich des Controllers keine prototypische Vererbung besteht. Wenn jedoch die Bereichseigenschaft der Anweisung wahr war (scope: true), anstatt den Geltungsbereich zu isolieren, dann musste scope.details ein Objekt sein, um den geänderten Wert im Controllerbereich zu sehen (den ich zuvor erläutert habe).

Die einzige Änderung, die erforderlich ist, ist, die scope.details = thi innerhalb der scope.$apply(function(){//code}) zu wickeln oder scope.$apply() am Ende der Rückgabefunktion von makeHappen aufzurufen.Die Frage ist, warum müssen Sie scope.$apply() anrufen oder bestimmten Code innerhalb scope.$apply(function() {//code}) setzen? Der Grund ist:

$ apply() wird verwendet, um einen Ausdruck in Winkel von außerhalb des der eckigen Rahmen auszuführen. (Zum Beispiel aus Browser-DOM-Ereignissen, setTimeout, XHR oder Bibliotheken von Drittanbietern).

In Ihrem Fall angebracht Sie einen Ereignis-Listener mm.addListener('click', makeHappen(eventName), false);. Die Funktion makeHappen wird aufgerufen, wenn auf den Marker geklickt wird. Es geschieht außerhalb des eckigen Kontextes. Angular weiß nicht, dass scope.details Wert geändert wird. Der Wächter für scope.details wird nicht aufgerufen und daher wird kein Update angezeigt. Und hier kommt die Lösung scope.$apply(). Wann immer Sie scope.$apply() anrufen, ruft es intern scope.$digest() auf, die tatsächlich alle Bindungen oder Beobachter aktualisieren.

Also, wann müssen Sie scope.$apply() anrufen? Hinter der Szene umschließt Angular fast den gesamten Code innerhalb von $ apply(), den Sie im Zusammenhang mit angular schreiben. Ereignisse wie ng-click oder $timeout oder $http Callbacks sind in scope.$apply() verpackt, so dass Sie es nicht explizit aufrufen müssen. Wenn Sie $ selbst anwenden, erhalten Sie einen Fehler.

Für weitere Informationen über $ anwenden, können Sie diese Links besuchen: https://docs.angularjs.org/api/ng/type/ $ rootScope.Scope # $ gelten http://jimhoskins.com/2012/12/17/angularjs-and-apply.html

ich gemacht habe, eine zupfen Sie besser die verschiedenen Szenarien Rahmen der Richtlinie zu verstehen und warum In einigen Fällen wird $apply benötigt. Bitte, sieh dir dieses Plunk an. http://plnkr.co/edit/96a646T6FuBhmjdLgJXq?p=preview

+0

Hallo, danke für deine Hilfe. Es als Objekt funktionieren zu lassen. Nur ein anderes Wort, ich habe scope hinzugefügt. $ Apply() nach dem Ändern von details.msg in der makeHappen-Funktion. . Wie auch immer, vielen Dank für Ihre Hilfe, freuen uns auf weitere Informationen/Link. – tytan

1

Ich denke, das dem hier berichtet ein ähnliches Problem ist: How to access parent scope from within a custom directive *with own scope* in AngularJS?

Hoffe es hilft!

+0

Danke für die Antwort, der Link, den Sie mir gegeben haben, ist über die Verwendung von Eigenschaften im Controller bei der Direktive, aber was ich tun möchte, ist den Wert der Eigenschaften in Controller bei Direktive zu ändern. Gibt es noch andere Links, die Sie vielleicht kennen, danke – tytan

+0

Ich habe tatsächlich die Methoden in der Verbindung vorher ausprobiert. Obwohl ich in der Direktive auf die Eigenschaften des Controllers zugreifen kann, kann ich seinen Wert nicht ändern. Es ist so, als hätte ich es nicht angewendet(). – tytan