2013-04-25 9 views
20

czy można zapisać przechwytywacz dla ng-click? Mam przycisk lub łącze, które prowadzi do usunięcia obiektu w backend. Chciałbym mieć okno dialogowe z potwierdzeniem (modalne) po prostu dodając atrybut do przycisku/łącza. Np .:Przechwytywanie ng-click w kątowym JS

<a href="#" ng-click="deleteIt(id)" confirmation-needed>Delete</a> 

Czy to możliwe z AngularJS? Czy istnieje lepsze podejście do rozwiązania tego problemu?

EDYCJA Metoda deleteIt znajduje się w różnych kontrolerach.

Thx

Odpowiedz

49

Włożyłam dyrektywę przykład w:

http://plnkr.co/edit/GJwK7ldGa9LY90bMuOfl?p=preview

Osiągam to, tworząc dyrektywę:

  1. z wyższym priority niż ngClick, tak że zostaje wezwany przed ngClick,
  2. dokonywania że terminal tak, że nie nazywają ngClick.
  3. słuchanie zdarzeń kliknięcia, a następnie ocena wartości ngClick, jeśli wiadomość jest w porządku.

Jako bonus, można przekazać w swoim komunikacie, takie jak:

<a href="#" ng-click="deleteIt(id)" 
    confirmation-needed="Really Delete?" 
     >Delete with custom message</a> 

Kod wygląda tak:

app.directive('confirmationNeeded', function() { 
    return { 
    priority: 1, 
    terminal: true, 
    link: function (scope, element, attr) { 
     var msg = attr.confirmationNeeded || "Are you sure?"; 
     var clickAction = attr.ngClick; 
     element.bind('click',function() { 
     if (window.confirm(msg)) { 
      scope.$eval(clickAction) 
     } 
     }); 
    } 
    }; 
}); 

nadzieję, że pomoże.

+0

Bardzo ładne, to było rozwiązanie, którego szukałem, dzięki! – Soccertrash

+0

To jest blisko, jak bym to zrobił .. Ale tutaj jest inny plunk, który działa prawie tak samo, z wyjątkiem nie obchodzi czy masz ng-kliknięcie czy nie .. http://plnkr.co/edit/Cwu15Z8U6ok0MMF8p6Ks? P = preview – ganaraj

+1

@ganaraj: To nie działa, gdy klikam Anuluj, ponieważ 'createEventHandler' JQLite kontynuuje iterowanie po wszystkich powiązanych zdarzeniach i nie zatrzymuje drugiego' bind ('click', ...) 'od bycia wezwanym. (Moja przeglądarka: Chrome w wersji 26.0.1410.65 na Mac OSX 10.6.8) – Piran

3

można wstrzykiwać $window do kontrolera, dzięki czemu można używać $window.confirm z swoim zakresem, wówczas:

<a href="#" ng-click="confirm('message') && deleteIt(id)">Delete</a> 
+0

Dzięki, @tosh! To postawiło mnie na dobrej drodze do tego, co musiałem zrobić. Poniżej zamieściłem następną odpowiedź, która ma tę samą koncepcję, ale łączy ją z dyrektywą, więc mogę dostosować okno dialogowe potwierdzenia. – Dustin

10

Poddałem się, aby odpowiedź Pirana zadziałała tak, jak bym tego chciał. Zamiast tego, po prostu zacząłem zastępując ngClick z własnej dyrektywy:

.directive('confirmClick', function() { 
    return { 
     restrict: 'A', 
     link: function(scope, elt, attrs) { 
      elt.bind('click', function(e) { 
       var message = attrs.confirmation || "Are you sure you want to do that?"; 
       if (window.confirm(message)) { 
        var action = attrs.confirmClick; 
        if (action) 
         scope.$apply(scope.$eval(action)); 
       } 
      }); 
     }, 
    }; 
}) 

Niniejsza dyrektywa nie ma nawet swój własny zakres, który ułatwia połączenie go z innymi dyrektywami znacząco. Zajmuje wszystko, czego potrzebuje bezpośrednio od attrs. Używa się go tak:

<span ng-show="editing" confirm-click="delete()" confirmation="delete confirmation message goes here">some text</span> 

Funkcja delete() musi istnieć gdzieś wyżej w łańcuchu $scope. Jestem pewien, że można to poprawić, przyglądając się, jak zaimplementowano ng-click, ale jeszcze się do niego nie dostałem!

+0

Czy potrzebne są $ $ ($ eval())? Wygląda na to, że działa dobrze, a tylko $ apply (action). – Priit

+1

Hmm ... Minęło trochę czasu, odkąd to napisałem ... Chyba nie potrzebujesz obu! – samson

5

Grałem z tym przez długi czas, ale asynchroniczna natura Angulara sprawia, że ​​trudno jest liczyć na to, że wszystkie dyrektywy będą ładnie współgrać ze sobą. Wtedy zobaczyłem odpowiedź @ tosh, która zmusiła mnie do myślenia.

myślę, że łączy w sobie wiele zalet: Tworzenie dyrektywę i Prepend ngClick

Więc, po prostu dodaj tę dyrektywę do aplikacji, a następnie dodać „potwierdzić kliknij” atrybut do linku, jak również funkcja confirmClick() do twojego ngClick.

Link:

<a href="#" ng-click="confirmClick() && deleteIt(id)" confirm-click>Delete</a> 

dyrektywa:

.directive('confirmClick', function() { 
    return { 
     link: function (scope, element, attrs) { 
      // setup a confirmation action on the scope 
      scope.confirmClick = function(msg) { 
       // msg can be passed directly to confirmClick('are you sure?') in ng-click 
       // or through the confirm-click attribute on the <a confirm-click="Are you sure?"></a> 
       msg = msg || attrs.confirmClick || 'Are you sure?'; 
       // return true/false to continue/stop the ng-click 
       return confirm(msg); 
      } 
     } 
    } 
}) 

ta jest bardzo podobna do wstrzykiwania standardowego potwierdzenia() okna, ale dlatego, że masz go w dyrektywie, można dostosować sposób wybrać aby uruchomić okno dialogowe potwierdzenia (może całkiem modalne, zamiast okna dialogowego).

**** **** BONUS ODPOWIEDŹ

grałem z tego więcej i zintegrowane rozwiązanie, które wykorzystuje jako modalne okno potwierdzenia, a nie w oknie domyślnej. Oto kompletne rozwiązanie: https://stackoverflow.com/a/23718694/1135826

Powiązane problemy