Formularze w dobrej formie cz. III – jQuery

Formularze w aplikacjach internetowych są dziś wszechobecne – pola wyszukiwania, zmiana statusu na FB, komentarze i multum innych. Póki znacząco nie zmienią się obecne interfejsy użytkownika, formularze będą pełniły bardzo ważną rolę. Rzućmy okiem, jak możemy je należycie stosować i obsługiwać. W tej części cyklu Formularze w dobrej formie – obsługa formularza za pomocą jQuery i AJAXa.

Oglądaliście Pulp Fiction?

  • Nie – najwyższy czas to nadrobić,
  • Tak – w tym cyklu też nie zachowamy chronologii, części I i II pojawią się później, będą też co najmniej 2 kolejne.

Przyjmijmy, że mamy już przygotowany formularz. Chcielibyśmy jednak, żeby jego wysłanie nie wiązało się z przeładowaniem – w końcu to 2012 rok naszej ery, a nie przed nią. Łatwość z jaką możemy to zrobić za pomocą jQuery jest ogromna. Niech kod naszego formularza będzie możliwie prosty – weźmy formularz wysyłania komentarza:

<form id="comment">
    <fieldset>
        <div id="message"></div>
        <label for="name">Imię</label>
        <input type="text" name="name" id="name" />
        <label for="email">E-mail</label>
        <input type="text" name="email" id="email" />
        <label for="comment">Komentarz</label>
        <textarea name="comment" id="comment"></textarea>
        <input type="submit" value="Wyślij" />
    </fieldset>
</form>

Wszystko tu wygląda elegancko, oczywiście patrząc w kod, bo w takiej postaci bez CSSa na stronie będzie to wyglądało biednie. Ale my nie o tym.

Użytkownik wpisuje co trzeba (tak póki co załóżmy, walidacją zajmiemy się później w tym cyklu) i klika Wyślij. Chcielibyśmy, żeby nie opuścił w ten sposób strony – nawet na chwilę. Dlatego uciekamy się do wykorzystania jQuery. Podejście pierwsze:

$(function($){
    $('form#comment').submit(function(event){
        event.preventDefault();
        $.ajax({
            'url' : 'answers.php',
            'type' : 'post',
            'dataType' : 'json',
            'data' : {
                'name' : $('input#name').val(),
                'email' : $('input#email').val(),
                'comment' : $('textarea#comment').val()
            },
            'success' : function(response){
                if (response.success){
                    $('div#message').html('Dodano komentarz');
                } else {
                    $('div#message').html('Nie udało się dodać Twojego komentarza');
                }
            }
        });
    });
});

Co tu się wyrabia? Po pierwsze – podpinamy funkcję anonimową do obsługi zdarzenia wysyłania formularza. Do tej funkcji przekazujemy obiekt zdarzenia. Jest nam to potrzebne, żeby zablokować standardowe wysyłanie formularza za pomocą metody preventDefault(). Warto zrobić to na samym początku obsługi wysyłania. Z nie do końca znanych mi powodów miewałem problemy z powstrzymaniem wysyłania, jeśli to nie była pierwsza operacja.

Dalej bierzemy się za wysłanie formularza za pomocą AJAXa.

Piszę o AJAXie z pełną świadomością, że wcale go nie użyję. Dlaczego? Ponieważ musiałbym wykorzystać XML do przekazania danych zwrotnych z serwera. Wykorzystam za to JSON, więc to raczej AJAJ niż AJAX. Więcej na ten temat poczytacie na blogu yarpo, a tymczasem wiedząc to, możemy kontynuować.

Do funkcji ajax przekazujemy obiekt konfiguracyjny. Większość pól jest oczywista. Nieco zamieszania wprowadza nazwa pola dataType – to format danych wracających od serwera. Kolejną ciekawą rzeczą jest pole success w którym trzymamy funkcję obsługującą odpowiedź od serwera. Nazwa success to też drobna zmyłka. Ta funkcja zostanie wywołana, gdy sukcesem zakończy się żądanie do serwera (który zwróci kod 200), ale niekoniecznie wykonywana na serwerze operacja – np. zapis do bazy. O rozróżnienie sukcesu od niepowodzenia operacji musimy zatroszczyć się sami – do tego w moim przykładzie służy pole success w odpowiedzi. Dzięki ustawieniu dataType na JSON argument response przekazany do tej funkcji success jest od razu interpretowany jako obiekt. Domyślną wartością tego pola jest, jak podaje dokumentacja, Intelligent Guess. Wybaczcie mi, ale ale nie pozostawię tego ustawienia zgadywaniu i podam je wprost.

Mamy więc działający formularz wysyłania komentarza. Ale co, jeśli chcielibyśmy obsłużyć formularz generowany dynamicznie – nie znając na etapie programowania liczby i nazw pól. Z jednej strony można by również dynamicznie wygenerować skrypt wysyłający formularz. Ale to średnio dobry pomysł. Lepiej byłoby znaleźć uniwersalny sposób na pobranie wszystkich danych z formularza. A taki sposób jest tuż za rogiem – jest nim wykorzystanie metody serialize obiektu jQuery przechowującego formularz. Z jej wykorzystaniem kod wygląda tak:

$(function($){
    $('form#comment').submit(function(event){
        event.preventDefault();
        $.ajax({
            'url' : 'answers.php',
            'type' : 'post',
            'dataType' : 'json',
            'data' : $('form#comment').serialize(),
            'success' : function(response){
                if (response.success){
                    $('div#message').html('Dodano komentarz');
                } else {
                    $('div#message').html('Nie udało się dodać Twojego komentarza');
                }
            }
        });
    });
});

Gdyby nie identyfikatory elementów w HTML i treść komunikatu, mielibyśmy tu całkowicie uniwersalny sposób obsługi ogólnego formularza za pomocą AJAX w jQuery. Możemy to podrasować np. za pomocą klasy nadanej formularzowi, a komunikat pobrać bezpośrednio z serwera.

$(function($){
    $('form.ajaxified').submit(function(event){
        event.preventDefault();
        var ajaxifiedForm = $(this);
        $.ajax({
            'url' : ajaxifiedForm.attr('action'),
            'type' : 'post',
            'dataType' : 'json',
            'data' : ajaxifiedForm.serialize(),
            'success' : function(response){
                ajaxifiedForm.children('div.message').html(response.message).addClass(response.status);
            }
        });
    });
});

W ten sposób, przy odpowiedniej strukturze HTML, obsłużymy wszystkie formularze na stronie, które mają posługiwać się AJAXem.

Więcej o podanych zagadnieniach:

Jedna myśl nt. „Formularze w dobrej formie cz. III – jQuery

  1. Widzę, że ktoś mnie poniekąd wywołał do tablicy 🙂

    Owszem, „Ajax” pisane jako rzeczownik moim zdaniem jest prawidłową formą. Dlaczego? Wojtek tu wskazał, że jego „Ajax” (choć On nadal pisał jako skrót „AJAX”) odnosi się m. in. do XML. Według mnie dzisiaj Ajax pełni rolę cepeenu. Mówiąc „jadę na CPN” nie masz na myśli stacji tej firmy, a jedynie stację paliw. Ajax dziś też jest po prostu czymś interaktywnym wykonywanym z poziomu JS. Więcej o tym można przeczytać w „JavaScript na poważnie” (można znaleźć na moim blogu)

    A jeśli chodzi o samą obsługę zdarzeń, to oczywiście jest też możliwa bez jQuery:)
    http://www.yarpo.pl/2011/06/04/walidacja-formularzy-obsluga-zdarzen/