2013-06-19 12 views
10

Bitte lassen Sie mich wissen, wenn Sie weitere Informationen benötigen oder möchte ich etwas zu klären. Ich habe viele verschiedene Dinge ausprobiert, um das herauszufinden, habe aber keine Lösung gefunden.AngularJS Zwei-Wege-Datenbindung in geschachtelten Direktiven

Ich bin relativ neu zu angularJS und ich versuche, eine App mit mehreren Schichten von Daten zu erstellen. Ich habe einige grundlegende Benutzerinformationen im Bereich des Körpers auf Controller PageController gespeichert. Ich habe dann ein Einstellungsformular, das mit $ routeParams (mit Controller SettingsController) lädt, die ein paar benutzerdefinierte Anweisungen für Templating-Zwecke enthält. Da die Direktiven verschachtelt sind, verwende ich die Einfügung, um die zweite in die erste zu laden. Das scheint alles in Ordnung zu sein.

Mein Problem ist, dass ich versuche, das Feld user.firstname von innerhalb der innersten Direktive verweisen und zweiseitige Datenbindung verwenden möchten, um Änderungen an der Textbox zu ermöglichen, den Wert im PageController-Bereich zu ändern. Ich weiß, dass viele dieser Probleme durch die Verwendung von Primitiven im ng-Modell verursacht werden, aber ich habe versucht, alles in ein zusätzliches Objekt zu setzen, sodass ich die prototypische Vererbung ohne Erfolg auslösen kann. Was mache ich hier falsch?

Hier ist ein JSFiddle meines Codes, so weit wie möglich reduziert, um das Problem zu isolieren. Wenn ich in diesem Beispiel das äußere Textfeld einschließe, das sich direkt im PageController-Bereich befindet, wird das innere Textfeld geändert, bis dieses Textfeld geändert wird und die Verbindung unterbrochen wird. Dies scheint genau wie das Problem der Verwendung von Primitiven, wie in anderen Fragen beschrieben, zu sein, aber ich kann nicht herausfinden, wo das Problem hier ist.

HTML:

<body class="event-listing" ng-app="app" ng-controller="PageController"> 
    <div class="listing-event-wrap"> 
     <input type="text" ng-model="user.firstname" /> 
     <div ng-controller="SettingsController"> 
      <section block title="{{data.updateInfo.title}}" description="{{data.updateInfo.description}}"> 
       <div formrow label="{{data.updateInfo.labels.firstname}}" type="textInput" value="user.firstname"></div> 
      </section> 
     </div> 
    </div> 
</body> 

Angular-Richtlinien:

app.directive('formrow', function() { 
return { 
    scope: { 
      label: "@label", 
      type: "@type", 
      value: "=value" 
    }, 
    replace: true, 
    template: '<div class="form-row">' + 
      '<div class="form-label" data-ng-show="label">{{label}}</div>' + 
      '<div class="form-entry" ng-switch on="type">' + 
       '<input type="text" ng-model="value" data-ng-switch-when="textInput" />' + 
      '</div>' + 
     '</div>' 
} 
}); 
app.directive('block', function() { 
return { 
    scope: { 
      title: "@title", 
      description: "@description" 
    }, 
    transclude: true, 
    replace: true, 
    template: '<div class="page-block">' + 
      '<h2 data-ng-show="title">{{title}}</h2>' + 
      '<p class="form-description" data-ng-show="description">{{description}}</p>' + 
      '<div class="block-inside" data-ng-transclude></div>' + 
      '</div>' 
} 
}); 

Angular Controller:

app.controller("PageController", function($scope) { 
    $scope.user = { 
     firstname: "John" 
    }; 
}); 
app.controller("SettingsController", function($scope) { 
    $scope.data = { 
     updateInfo: { 
      title: "Update Your Information", 
      description: "A description here", 
      labels: { 
       firstname: "First Name" 
      } 
     } 
    } 
}); 

Antwort

9

Ich bin so rry für den vorherigen Code. Versuchen Sie dies stattdessen:

Anstatt den tatsächlichen Wert zu übergeben, übergebe ich jetzt das Objekt + einen Zeiger auf den richtigen Wert im Inneren. Ich fügte hinzu, 'refObject' hier:

<body class="event-listing" ng-app="app" ng-controller="PageController"> 
    <div class="listing-event-wrap"> 
     <input type="text" ng-model="user.firstname" /> 
     <div ng-controller="SettingsController"> 
      <section block title="{{data.updateInfo.title}}" description="{{data.updateInfo.description}}"> 
       <div formrow label="{{data.updateInfo.labels.firstname}}" type="textInput" refobj='user' value="firstname"></div> 
      </section> 
     </div> 
    </div> 
</body> 

und ich fügte refobj + Wert hier:

app.directive('formrow', function() { 
    return { 
     scope: { 
      label: "@label", 
      type: "@type", 
      value: "@value", 
      refobj: "=" 
     }, 
     replace: true, 
     template: '<div class="form-row">' + 
      '<div class="form-label" data-ng-show="label">{{label}}</div>' + 
      '<div class="form-entry" ng-switch on="type">' + 
     '<input type="text" ng-model="refobj[value]" data-ng-switch-when="textInput" />' + 
      '</div>' + 
     '</div>' 
    } 
+0

Vielen Dank für eine schnelle Antwort! Ich probierte die Geige aus, aber es scheint das Gleiche zu tun wie die, die ich gepostet habe. Was ist das Ziel, es in einen Funktionsisolat-Bereich zu ändern? – princjef

+0

Ich habe refobj hinzugefügt, so dass du 'firstname' nicht innerhalb der Direktive aufrufen musst, da ich sicher bin, dass dies generisch sein soll. – Nir

+0

Das ist wirklich schlau! Hatte nicht gedacht, die Array-Notation anstelle des Punktes zu verwenden. Dies wird für meine Bedürfnisse funktionieren. Vielen Dank! – princjef

8

Da die Textbox in der Richtlinie eine primitive verwendet anstelle eines Objekts für sein Modell (ng-model="value" statt ng-model="someobj.somevalue"), sein Modell wird nur auf dem lokalen Bereich erstellt und der Eltern hat keinen Zugriff darauf.

Das Update ist die Richtlinie Textbox Modell mit dem dot rule als Objekteigenschaft zu definieren:

ng-model="value.firstname" 

Dann passieren das ganze user Objekt in die Richtlinie, anstatt nur die primitiven Eigenschaft:

<div formrow ... value="user"></div> 

Here is a demo

+0

Oh ich sehe wo ich falsch gelaufen bin. Danke für die Einsicht – princjef

+0

Hey, ich habe deine Demo vereinfacht, nur um die Dinge klarer zu sehen. Es scheint, es funktioniert mit komplexen Objekten, aber nicht mit einfachen Eigenschaften ... [Hier ist aktualisierte Version] (http://jsfiddle.net/BXRnM/4/). Kannst du sehen warum? – Dmitry

+0

@Dmitry Ihr Beispiel der einfachen Eigenschaft führt OPs Fehler wieder ein.Um es kurz zu machen, erfordert die Vererbung des Winkelbereiches Objekte anstelle einfacher primitiver Variablen. Dies ist eine direkte Folge der prototypischen Vererbung in JavaScript. Sie könnten sich [[diese Antwort] ansehen (http://stackoverflow.com/questions/16928341/update-parent-scope-variable/16929117#16929117)] Ich gab woanders um ein anderes Beispiel zu sehen oder [[this Fragen und Antworten] (http://stackoverflow.com/questions/14049480/what-are-the-nuances-of-scope-prototypal-prototypical-inheritance-in-angularjs)] für eine detailliertere Erklärung. – sh0ber

0

Das Problem, dass ich s verursacht durch ng-switch, Von doc Understanding scope von git.

ng-Switch-Bereich Vererbung funktioniert genau wie ng-include. Wenn Sie also eine 2-Wege-Datenbindung mit an ein Primitiv im übergeordneten Bereich benötigen, verwenden Sie $ parent oder ändern Sie das Modell als Objekt und binden Sie dann an eine Eigenschaft dieses Objekts. Dadurch wird verhindert, dass der Bereich "Kindbereich" die Eigenschaften des übergeordneten Bereichs " " verdeckt/überschattet.

also wenn Sie etwas Text in das Textfeld eingeben. unter dem Code wird für den Bereich ng-switch ausgeführt werden.

$scope.value="the text you typed"

So wird es nicht die Prototypkette konsultieren value .this suchen eine neue Eigenschaft für ng-switch Bereich erstellt.

Wie bezeugen?

Wenn Sie value zu $parent.value ändern. Alles wird gut funktionieren. denn in der ng-switch für den primitiven Typ (Angularjs würde die value als primitiven Typ erkennen, wenn es keinen Punkt gibt) $parent wird auf formrow Richtlinie Bereich beziehen.

Versuchen Sie, die ng-switch zu entfernen oder tun, wie das Dokument sagt. Das Problem wird verschwinden.

Und noch wichtiger, das Dokument empfiehlt uns immer einen Punkt . zu verwenden, um das Modell verweisen, wenn eine bidirektionale Bindung anwenden.

Wenn ich etwas falsches gesagt habe. Bitte korrigieren Sie mich und machen Sie es richtig. Danke.

Verwandte Themen