Ajax Forms with Rails 3-najlepsza praktyka?

Co jest uważane za sposób Rails dla formularzy Ajax

Do dzisiaj uważałem, że sposób, w jaki używam Rails forms + jQuery UJS był na to właściwy, ale aktualizacja do jQuery 1.7 'zepsuła' sposób, w jaki dotychczas to robiłem.

Jak to zrobić?

Chcę używać Ajax z moimi formularzami. Odpowiedź ajax powinna albo renderować formularz ponownie (np. gdy wystąpią błędy) lub przekierować na stronę sukcesu. (Powinno być może zrobić więcej, jak Pokazywanie modali, ale chcę zachować ten przykład proste).

1. Używając EJS i $('#formid').html(...)

Tak robiłem do tej pory. Moja odpowiedź ajax był szablon ejs, który zwrócił kod javascript, aby ponownie renderować formularz (z błędami) lub w zależności od tego, czy był to błąd przekierował użytkownika na stronę sukcesu: {]}
<% unless @success_submit %>
$('#form_wrapper').html('<%= escape_javacsript( render :partial => 'form' ) %>'); 
<% else %>
document.location = '/success_thank_you';
<% endif %>

Teraz wyobraź sobie, że formularz zawiera komunikat o błędzie div jak

<div class="error_message">BlaBla</div>

Aby dodać ładny efekt miałem ogólne jQuery.live event związany z ajax complete, który podświetlił błędy.

$('form').live('ajax:complete', function() {
   // do stuff like highlighting all error messages in that form
}); 

To już nie działa z jQuery1.7 + jQuery-ujs (prawdopodobnie z dobrych powodów). Więc myślę, że sposób, w jaki to zrobiłem, nie był w porządku.

2. Używając powyższego sposobu, ale powtórzę się

Zamiast wiązania zdarzenia ajax:complete mogłem zrobić "błąd podkreślania rzeczy" w EJS jak

$('#form_wrapper').html('<%= escape_javascript( render :partial => 'form' ) %>');
$('#form_wrapper form .error_message').fadeIn();

Ale oznaczałoby to, że musiałbym powtarzać drugi wiersz w prawie każdym EJS, który renderuje formy. I oczywiście chcę, żeby było suche.

3. Ajax odpowiedź renderuje czysty html, ajax: wyświetlanie kompletnych uchwytów zdarzeń

Zupełnie innym rozwiązaniem byłoby to, że odpowiedź ajax po prostu renderuje czysty html, a mój Niestandardowy ajax: complete handler zajmie się wyświetlaniem formularza. Opiekun będzie wyglądał tak:

$('form').live('ajax:success', function(ev, data, status, xhr) {
  $(this).html(data);
  // and e.g. highlight stuff
  $(this).children('.error_message').fadeIn();
});
To by zadziałało. Ale co teraz zrobić, jeśli mój serwer zdecyduje się nie renderować formularza ponownie (np. po udanej rejestracji), ale zamiast tego przekierować na inny adres url lub pokazując formularz modalny. Serwer może odpowiedz czymś takim
<script>
   document.location = '/success.blabla/';
</script>

Ale czy to dobre rozwiązanie ?

4. Custom JSON protocol

Prawdopodobnie dobrym rozwiązaniem byłoby użycie wersji 3, ale zamiast po prostu zastąpić obecną formę zwracanym html, moglibyśmy stworzyć niestandardowy protokół json. W ten sposób możemy nawet pozwolić serwerowi odpowiedzieć takimi rzeczami jak

    Pierwszy pokaz modalny (jak "sukces rejestracji")
  1. przekierowanie do strony logowania

Ajax: sukces handler może sprawdzić, czy odpowiedź jest czystym html, w takim przypadku zastąpi obecną formę kodem html. Ale jeśli odpowiedź jest tablicą JSON, poradzi sobie z tym, np. serwer odpowiada

{ html: '<%= render :partial => 'something' %>', 
  show_modal:  '<%= render :partial => 'modal_template' %>',
  redirect_after_modal: '/login_page'
}

Ajax: Success handler poradziłby sobie z tym jak

$('form').live('ajax:success', function(ev, data, status, xhr) {
   // try parsing json
   if (data.json['show_modal') { // show modal code.... }; 
   if (data.json['redirect']) { document.location=data.json['redirect']);...
});

Jak ty to robisz

Oczywiście istnieje wiele sposobów obsługi formularzy ajax. Ale jak to robisz i co jest uważane za najlepszą praktykę z Rails ?

Author: Christian Szardenings, 2011-11-18

2 answers

Więc, udało mi się sprowadzić twój problem tylko do jquery, i na pewno, to działa w jquery 1.6.4, ale nie w jquery 1.7 .

Wydaje się, że jeśli podmienisz element w DOM, a następnie uruchomisz Zdarzenie w obiekcie jquery utworzonym z oryginalnego elementu, wersja 1.6.4 nadal uruchomi Zdarzenie w oryginalnej lokalizacji elementów i pozwoli mu propagować DOM. 1.7 jednak nie uruchomi tego elementu (co ma większy sens).

Właśnie zrobiłem przeszukaj jQuery 1.7 changelog i oczywiście, oto dwa bilety, które poprawiły to zachowanie: 9951 oraz 10489.

Aby odpowiedzieć na twoje pytanie o to, co jest najlepszą praktyką dla osiągnięcia czegoś takiego, powiedziałbym, Przejmij kontrolę nad tym, w jakiej kolejności twoje wydarzenia strzelają. jQuery automatycznie wykonuje JS zwracane w odpowiedziach ajax, co oznacza, że nie masz kontroli nad tym, kiedy to się stanie.

Najprostszym sposobem modyfikacji kodu będzie be do zwrócenia samej części HTML, a następnie użyj jquery, aby zastąpić formularz zwracanym HTML w ajax:complete LUB ajax:success/ajax:error pomocnicy. W ten sposób możesz mieć pewność, że rzeczy dzieją się w dokładnej kolejności, w jakiej chcesz.

Aby zobaczyć jak dokładnie to osiągnąć, spróbuj przeczytać [mój artykuły]:

Lub zobacz jQuery-UJS wiki dla tych linków i więcej.

 8
Author: jangosteve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-18 16:47:06

Nie wiem, czy już tego potrzebujesz, ale tutaj co zrobiliśmy, aby zaimplementować formularze za pomocą AJAX

Załóżmy, że mamy działanie, które wygląda jak

def new
  @saved_search = SavedSearch.new
new

def create
  if @saved_search.save
    respond_to do |format|
      format.js { render :saved }
    end
  else
    respond_to do |format|
      format.js { render :new }
    end
  end
end

I mamy formę, która wygląda jak

# app/views/saved_searches/new.html.erb
<%= form_for @saved_search,  url: saved_searches_path(format: :js), remote: true do |f| %>
  <div class="form">
    <div class="content">
      <div class="field">
        <%= f.label(:name, t(".name_search"), class: "label") %>
        <%= f.text_field(:name, size: "25", autofocus: "autofocus") %>
      </div>

      <div class="clear"></div>
    </div>

    <footer class="clear">
      <div class="left">
        <%= f.button t(".save"), class: "button" %>
      </div>
      <div class="clear"></div>
    </footer>
  </div>
<% end %>

I oczywiście chcemy zwrócić błąd, jeśli niektóre pola są nieprawidłowe. Oto sztuczka

# app/views/saved_searches/new.js.erb
<%- @saved_search.errors.keys.each do |field| %>
  $('#saved_search_<%= field %>').after("<span class=\"errors\">&nbsp;<%=   @saved_search.errors[field].join(',')  %></span>")
  $('#saved_search_<%= field %>').wrap('<div class="field_with_errors" />');;
<% end %>

To nie hamuje wiązań JQuery lub wywołania zwrotnego, ale nadal wyświetla błędy.

Myślę, że dobrym pomysłem byłoby napisanie jakiejś formy konstruktor, który będzie mógł zarówno renderować formularz HTML, jak i zwrócić kilka dyrektyw JQuery dla pól formularza, biorąc

Rails.configuration.action_view.field_error_proc

Do rozważenia

 0
Author: Max,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-20 17:35:32