Voici mon controller avec deux simples actions (j'ai volontairement simplifié l'exemple).
# app/controllers/dishes_controller.rb
class DishesController < ApplicationController
# affiche le formulaire
def edit
render '_form', locals: {dish: @dish}, layout: false
end
# met à jour le plat
def update
if @dish.update(dish_params)
# renvoie la liste des plats avec la modification
render 'dishes/_list', locals: {dishes: @restaurant.dishes_ordered}, layout: false
else
# renvoie le formulaire avec un status d'erreur
render '_form', locals: {dish: @dish}, layout: false, status: :unprocessable_entity
end
end
end
Et voici mon formulaire
<!-- app/views/dishes/_form.html.erb -->
<%= bootstrap_form_for dish, remote: true do |f| %>
<%= render 'shared/errors_form', model: dish %>
<%= f.text_field :name, hide_label: true, placeholder: 'Nom' %>
<!-- d'autres champs ici -->
<%= f.submit 'Confirmer' %>
<% end %>
Rails nous simplifie largement la vie car l'attribut remote: true
gère pour nous l'envoie du formulaire en AJAX. Il nous reste donc "juste" à implémenter les actions à effectuer lorsque
- le plat est mis à jour
// app/assets/javascripts/dishes.js
$(document).on(
"ajax:success",
"form.edit_dish",
function (e, data, status, xhr) {
// le formulaire a été envoyé correctement et le plat a été mis à jour
// on récupère donc le résultat et on met à jour la liste des plats
$("#dishes-list").html(xhr.responseText);
// on ferme le jquery-ui dialog
$(".ui-dialog").remove();
}
);
- le formulaire contient une erreur.
// app/assets/javascripts/dishes.js
$(document).on(
"ajax:error",
"form.edit_dish",
function (e, xhr, status, error) {
// le plat n'a pas été mis à jour, sûrement à cause d'une erreur de donnée,
// on récupère donc le formulaire renvoyé par notre controlleur et on écrase l'ancien
var form = $(this);
form.parent().html(xhr.responseText);
}
);
Ruby on Rails est magique!