2013-04-29 5 views
47

abgerufen werden Hier ist meine PLNKR: http://plnkr.co/edit/n8cRXwIpHJw3jUpL8PX5?p=preview Sie müssen auf ein li Element klicken und das Formular wird angezeigt. Geben Sie eine zufällige Zeichenfolge ein und klicken Sie auf "Nachricht hinzufügen". Anstelle des Textarea-Textes werden Sie undefiniert.Textbereich kann nicht in angularjs

Markup:

<ul> 
    <li ng-repeat="ticket in tickets" ng-click="select(ticket)"> 
     {{ ticket.text }} 
    </li> 
</ul> 
<div ui-if="selectedTicket != null"> 
    <form ng-submit="createNotice(selectedTicket)"> 
     <textarea ng-model="noticeText"></textarea> 
     <button type="submit">add notice</button> 
    </form> 
</div> 

JS Teil:

$scope.createNotice = function(ticket){ 
    alert($scope.noticeText); 
} 

gibt 'undefined'. Ich habe festgestellt, dass dies nicht funktioniert, wenn man ui-if angular-ui verwendet. Irgendwelche Ideen, warum das nicht funktioniert? Wie man es repariert?

Antwort

86

Ihr Problem liegt im ui-if-Teil. Es scheint, dass Winkel-ui einen neuen Bereich für alles schafft in dieser Richtlinie so, um den übergeordneten Bereich zuzugreifen, können Sie etwas tun müssen:

<textarea ng-model="$parent.noticeText"></textarea> 

Statt

<textarea ng-model="noticeText"></textarea> 
58

Dieses Problem geschah zu mir, während Sie nicht die ng-if Direktive auf Elementen verwenden, die das Textarea-Element umgeben. Während die Lösung von Mathew korrekt ist, scheint der Grund ein anderer zu sein. Die Suche nach diesem Problem verweist auf diesen Post, also habe ich beschlossen, dies zu teilen.

Wenn Sie die AngularJS Dokumentation sehen Sie hier https://docs.angularjs.org/api/ng/directive/textarea, können Sie sehen, dass Angular seine eigene Richtlinie fügt <textarea> genannt, dass „überschreibt“ die Standard-HTML-textarea Element. Dies ist der neue Bereich, der das ganze Durcheinander verursacht.

Wenn Sie eine Variable wie

$scope.myText = 'Dummy text'; 

in Ihrem Controller und binden, dass auf dem textarea Element wie folgt

<textarea ng-model="myText"></textarea> 

AngularJS für diese Variable im Geltungsbereich der Richtlinie aussehen wird. Es ist nicht da und so geht er runter zu $ ​​eltern. Die Variable ist dort vorhanden und der Text wird in die textarea eingefügt. Beim Ändern des Textes in textarea ändert Angular NICHT die Variable des Elternteils. Stattdessen wird eine neue Variable im Gültigkeitsbereich der Richtlinie erstellt, und die ursprüngliche Variable wird nicht aktualisiert. Wenn Sie die textarea an die Variable der Eltern binden, wie von Mathew vorgeschlagen, wird Angular immer an die richtige Variable binden und das Problem ist weg.

<textarea ng-model="$parent.myText"></textarea> 

hoffen, dass dies die Dinge klar für andere Personen auf diese Frage kommen und und denkt „WTF, ich bin nicht ng-if oder durch eine andere in meinem Fall mit!“ wie ich es tat, als ich hier gelandet;)

Update: Verwenden Sie Controller-wie Syntax

wollte dies vor langer hinzufügen, aber es hatte keine Zeit zu tun. Dies ist der moderne Stil der Controller zu bauen und sollte anstelle der oben genannten $parent Sachen verwendet werden. Lesen Sie weiter, um herauszufinden, wie und warum.

Seit AngularJS 1.2 gibt es die Möglichkeit, das Controller-Objekt direkt zu referenzieren, anstatt das Objekt $scope zu verwenden.

für ihre Zustände
<div ng-controller="MyController as myc"> [...] </div> 

Beliebte Routing-Module (d UI Router) bieten ähnliche Eigenschaften: Dies kann durch Verwendung dieser Syntax in HTML-Markup erreicht werden. Für UI-Router verwenden Sie die folgende in Ihrem Zustand Definition:

[...] 
controller: "MyController", 
controllerAs: "myc", 
[...] 

Das uns das Problem mit verschachtelten oder falsch adressierte Bereiche umgehen hilft. Das obige Beispiel würde auf diese Weise erstellt werden. Zuerst der JavaScript-Teil. Einfach gesagt, verwenden Sie einfach nicht die $scope Referenz, um Ihren Text festzulegen, verwenden Sie einfach this, um die Eigenschaft direkt an das Controller-Objekt anzuhängen.

angular.module('myApp').controller('MyController', function() { 
    this.myText = 'Dummy text'; 
}); 

Das Markup für die textarea mit Controller-wie Syntax würde wie folgt aussehen:

<textarea ng-model="myc.myText"></textarea> 

Dies ist der effizienteste Weg, Dinge wie dies heute zu tun, weil es das Problem mit verschachtelten Bereichen löst damit wir zählen können, wie viele Schichten wir an einem bestimmten Punkt tief sind. Die Verwendung mehrerer verschachtelter Direktiven innerhalb von Elementen mit einer Direktive ng-controller könnte bei der Verwendung der alten Art der Referenzierung von Bereichen zu so etwas führen. Und das will niemand wirklich den ganzen Tag machen!

<textarea ng-model="$parent.$parent.$parent.$parent.myText"></textarea> 
+2

Große ausführliche Erklärung! Sehr hilfreich! – Wolfgang

+0

rettete mein Leben. Danke für die Erklärung! – NewestStackOverflowUser

2

Es ist in der Tat ui-if, die das Problem verursacht. Angular, wenn Direktiven Teile des Doms basierend auf dem Ausdruck zerstören und neu erstellen. Dies ist der neue Bereich und nicht die Textarea-Direktive, wie Marandus vorgeschlagen hat.

Hier ist ein Beitrag zu den Unterschieden zwischen ngIf und ngShow, die diese gut beschreibt what is the difference between ng-if and ng-show/ng-hide.

23

Bind das Textfeld zu einem Eigenschaft Umfang variable anstatt direkt auf einen Umfang Variable:

Controller:

$scope.notice = {text: ""} 

Vorlage:

<textarea ng-model="notice.text"></textarea> 
+1

Das hat bei mir in Angular 1.5 funktioniert. Bizarre Beschränkung, ich bin mir ziemlich sicher, dass das früher (in 1.3?) Funktioniert hat und direkt an eine Scope-Variable gebunden ist ... – robru

+1

Diese Lösung scheint besser zu sein als $ parent.notice !! – Paritosh

+0

Ihre Lösung hat funktioniert. Eine Erklärung, warum die direkte Bindung fehlgeschlagen ist? – Shivendra