2013-04-29 17 views
47

Oto mój plnkr: http://plnkr.co/edit/n8cRXwIpHJw3jUpL8PX5?p=preview Musisz kliknąć na element li, a pojawi się formularz. Wpisz losowy ciąg i naciśnij "dodaj ogłoszenie". Zamiast tekstu textarea otrzymasz niezdefiniowany.Nie można uzyskać wartości textarea w 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 część: 'nieokreślone'

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

powraca. Zauważyłem, że to nie działa podczas używania ui-if z kanciastego-ui. Wszelkie pomysły, dlaczego to nie działa? Jak to naprawić?

Odpowiedz

86

Twój problem leży w części ui-if. Wydaje się, że kątowe-ui tworzy nowy zakres cokolwiek w tej dyrektywy tak, aby uzyskać dostęp do zakresu nadrzędnego, trzeba zrobić coś takiego:

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

Zamiast

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

Ten problem się dla mnie, gdy nie używam dyrektywy ng-if dotyczącej elementów otaczających element textarea. Podczas gdy rozwiązanie Mathew jest poprawne, powód wydaje się być inny. Wyszukiwanie tego problemu wskazuje na ten post, więc postanowiłem to udostępnić.

Jeśli spojrzeć na dokumentacji angularjs tutaj https://docs.angularjs.org/api/ng/directive/textarea, można zobaczyć, że kątowa dodaje własną dyrektywę o nazwie <textarea> że „przesłonięcia” domyślnym HTML textarea elementem. To jest nowy zakres, który powoduje cały bałagan.

Jeśli masz zmienną jak

$scope.myText = 'Dummy text'; 

w kontrolerze i wiążą że do elementu textarea jak tego

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

angularjs będzie szukać tej zmiennej w zakresie dyrektywy. Nie ma go i dlatego idzie do rodzica. Zmienna jest tam obecna, a tekst jest wstawiany do textarea. Zmieniając tekst w textarea, Angular NIE zmienia zmiennej rodzica. Zamiast tego tworzy nową zmienną w zakresie dyrektywy, a zatem pierwotna zmienna nie jest aktualizowana. Jeśli zwiążesz textarea ze zmienną rodzicielską, jak sugeruje Mathew, Angular zawsze będzie wiązał się z właściwą zmienną, a problem zniknął.

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

nadzieję, że to jasne rzeczy dla innych osób przybywających do tego pytania i i pomyśleć „WTF, nie używam ng-if lub jakakolwiek inna dyrektywa w moim przypadku!” tak jak ja, kiedy pierwszy raz wylądował tutaj;)

Aktualizacja: Użyj kontrolera jako składni

chcielibyście dodać to na długo przed, ale nie znalazł czasu, aby to zrobić. Jest to nowoczesny styl budowania kontrolerów i powinien być używany zamiast powyższych rzeczy. Czytaj dalej, aby dowiedzieć się, , jak i dlaczego .

Od AngularJS 1.2 istnieje możliwość bezpośredniego odniesienia do obiektu kontrolera zamiast korzystania z obiektu $scope. Można to osiągnąć za pomocą tej składni znaczników HTML:

<div ng-controller="MyController as myc"> [...] </div> 

popularnych modułów routingu (tzn UI Router) zapewniają podobne właściwości do swoich państw. Dla UI Router użyć następujących definicji państwa:

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

To pomaga nam obejście problemu z zagnieżdżonych lub niewłaściwie skierowane zakresów. Powyższy przykład zostanie skonstruowany w ten sposób. Najpierw część JavaScript. Prosto, po prostu nie używaj referencji $scope, aby ustawić tekst, wystarczy użyć this, aby dołączyć właściwość bezpośrednio do obiektu kontrolera.

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

Znaczniki dla textarea z kontrolera jako składni będzie wyglądać następująco:

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

Jest to najbardziej skuteczny sposób, aby robić rzeczy, jak ten dzisiejszy, ponieważ rozwiązuje problem z zagnieżdżonych zakresów sprawiają, że policzymy ile warstw jest głęboko w pewnym punkcie. Używanie wielu dyrektyw zagnieżdżonych wewnątrz elementów za pomocą dyrektywy ng-controller mogło prowadzić do czegoś podobnego w przypadku korzystania ze starego sposobu odwoływania się do zakresów. I nikt tak naprawdę nie chce tego robić przez cały dzień!

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

Bardzo szczegółowe wyjaśnienie! Bardzo przydatne! – Wolfgang

+0

Uratowałem moje życie. Dziękuję za wyjaśnienie! – NewestStackOverflowUser

2

Jest rzeczywiście ui-if że stwarza problem. Kątowe, jeśli dyrektywy niszczą i odtwarzają fragmenty drzewa dom w oparciu o wyrażenie. W ten sposób powstał nowy zakres, a nie dyrektywa tekstowa, jak sugeruje marandus.

Oto post na temat różnic między ngIf i ngShow, który opisuje to dobrze- what is the difference between ng-if and ng-show/ng-hide.

23

Bind textarea do zakresu zmiennej własności zamiast bezpośrednio do zmiennej zakres:

kontroler:

$scope.notice = {text: ""} 

szablon:

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

To zadziałało dla mnie w Angular 1.5. Dziwne ograniczenie, jestem prawie pewien, że to działało (z powrotem w 1.3?) Związane bezpośrednio z zmienną zakresu ... – robru

+1

To rozwiązanie wydaje się lepsze niż '$ parent.notice' !! – Paritosh

+0

Twoje rozwiązanie zadziałało. Jakiekolwiek wyjaśnienie, dlaczego bezpośrednie połączenie nie powiodło się? – Shivendra

Powiązane problemy