2013-04-09 15 views
29

Próbuję utworzyć dyrektywę, która powinna wykonywać niektóre akcje, gdy pole wejściowe jest oznaczone jako nieprawidłowe. W tym przykładzie pozwala zakładać Mam dyrektywę, która sprawdza, czy wejście jest liczbą pierwszą, a ja chcę stworzyć dyrektywę, która dodaje klasę do elementu kiedy jest nieprawidłowy:Ważność zegarka zgodnego z AngularJS

<input type="text" ng-model="primeNumber" validate-prime invalid-add-class="error"> 

validate-prime używa analizatory składni i formatery na modelu ng, aby zaktualizować poprawność modelu.

Teraz chcę, aby dyrektywa o nieprawidłowej klasie dodawała klasę "błąd", gdy model jest nieprawidłowy, i aby usunąć ją, gdy jest ona ważna. Innymi słowy, powinien obejrzeć właściwość $ valid (lub $ invalid) kontrolera modelu. Jednak nie mogę wymyślić, jak to działa. Próbowałem:

link : function(scope, element, attrs, ctrl) { 
    ctrl.$watch("$valid", function(newVal, oldVal) { 
    //never fired 
    }); 
} 

Być może mogłem obejrzeć niektóre zmienne w zakresie, ale nie wiem, którą zmienną oglądać.

Jak mogę otrzymać powiadomienie o zmianie ważności modelu?

+0

Jeśli możesz udostępnić swoją dyrektywę, będzie miło! –

+0

Nie pamiętam, czego dokładnie używałem, ale drugie rozwiązanie CaioToOn jest już prawie całą linkiem. Tylko ciało drugiej funkcji powinno być wypełnione działaniem, które chcesz, gdy zmienia się ważność. – Tiddo

Odpowiedz

60

Jeśli masz <form>, dodać do niego name (pozwala zakładać „MyForm”) i name do swojego wejścia (pozwala zakładać myInput). Powinieneś być w stanie $watch tym przez:

scope.$watch('myForm.myInput.$valid', function(validity) {}) 

Jeśli nie masz form, zawsze można oglądać funkcję. W ten sposób:

scope.$watch(function() { return ctrl.$valid; }, function(validity){}); 

można przeczytać więcej na temat podejścia formy here.

+1

Twoje drugie podejście zrobiło to za mnie, dzięki! – Tiddo

7

Naszym ogólnym celem powinno być sprawienie, aby dyrektywa działała niezależnie od jednej formy lub wkładu. W jaki sposób możemy zezwolić jej na odczytanie lokalnej właściwości $valid bez bezwzględnego wiązania jej z konkretną nazwą wejściową?

Wystarczy użyć require: 'ngModel' jako jednej z właściwości konfiguracji dyrektywy. Spowoduje to wstawienie lokalnego kontrolera ngModel jako czwartego argumentu funkcji łącza, a użytkownik może umieścić kod $watch bezpośrednio pod numerem $valid bez konieczności powiązania implementacji dyrektywy z konkretną formą lub wejściem.

require: 'ngModel', 
link: function postLink(scope, element, attrs, controller) { 
    scope.inputCtrl = controller; 
    scope.$watch('inputCtrl.$valid', handlerFunc) 
} 

Przewodnik powinien konsekwentnie wywoływać zmiany w $ valid z tą strukturą. Zobacz this Fiddle, gdzie dane wejściowe są sprawdzane pod kątem wzoru kodu pocztowego w USA lub Zip + 4. Otrzymasz alert za każdym razem, gdy zmieni się jego ważność.

EDYCJA 3/21/14: Ten post został wcześniej zawieszony na moim złudzeniu, naprawiając niewłaściwą przyczynę problemu z implementacją. Moja wina. Powyższy przykład usuwa tę fiksację. Dodałem też skrzypce, pokazując, że to podejście faktycznie działa i zawsze było, po dodaniu cytatów wokół wyrażenia zegarka.

+0

Czy na pewno to działa? Ponieważ dla mnie wydaje się, że 'inputCtrl. $ Valid' zostanie ocenione raz (po uruchomieniu funkcji łącza) i że wynik zostanie przekazany do' scope. $ Watch'. Oznaczałoby to, że rzeczywiste wywołanie to albo 'scope. $ Watch (true, handlerFunc)' albo 'scope. $ Watch (false, handlerFunc)', z których oba nie powodują oglądania zmiennej. – Tiddo

+0

'inputCtrl. $ Valid' jest odniesieniem do właściwości obiektu, a nie wartością pierwotną. Będzie on oceniany jako taki za każdym razem, gdy uruchomi się '$ watch'. Pracuję nad osobistymi projektami, ale obecnie nie mam dobrej publicznej wersji demo. – XML

+1

AFAIK 'inputCtrl. $ Valid' jest pierwotny. Jest to albo "true", "false" lub "undefined", z których wszystkie są prymitywami. Nie można tworzyć odwołań do właściwości obiektów, tylko do samych obiektów w JavaScript. Zobacz także ten JSFiddle: http://jsfiddle.net/9Mh92/2/. Jak widać, twój kod nie uruchamia wywołania zwrotnego, tylko z cytatami, które robi. Dzieje się tak, ponieważ nie można utworzyć odwołania do żadnego prymitywu. Umieszczając cudzysłowy wokół 'inputCtrl. $ Valid', instruujesz kątowo, aby ocenić to wyrażenie w bieżącym zakresie, a zatem działa. – Tiddo

12

Jeśli nie masz <form /> można łatwo dostać jeden:

w definicji dyrektywy:

require: '^form' 

a następnie w swojej funkcji łącza, formularz jest przekazywany jako czwarty parametr:

link: function (scope, element, attr, ctrl) { 

teraz nie muszą ciężko kodem formularz lub pole wprowadzania do wykonywania dolarów zegarek:

scope.$watch(ctrl.$name + '.' + element.attr('name') + '.$valid', 
function (validity) {}); 
+0

To było idealne. Chociaż z jakiegoś powodu musiałem użyć 'ctrl [0]. $ Name' - nie wiem, dlaczego moja kontrola zwracała tablicę 1-ego formularza ... – DoubleA

+1

zwróci tablicę, jeśli atrybut" require "zostanie przekazany tablicy (Podejrzewam, że to dla ciebie) – pixelbits

Powiązane problemy