2012-04-07 8 views
19

Dies könnte eine der schwierigeren Fragen sein, die ich gestellt habe, aber ich bin seit ein paar Tagen festgefahren, und ich dachte, es wäre am besten, Unterstützung von der erfahrenere Rails-Community.AJAX-Formular (mit simple_form) mit erhaltener Fehlerüberprüfung

ich auf einem Dummy-App arbeite, die in etwa diesen Leitfaden folgt ... ajax/jquery tutorial ...

meine eigenen Anpassungen zu machen, die Führung hat mir geholfen, eine „Marke“ zu erstellen (enthält verschachtelte Modelle „Modell“, "submodel" und "style") Einreichungsformular (mit simple_form) und Markenauflistung auf der gleichen Seite .. Das funktioniert einwandfrei, und die Validierung (für meine Modelle) wird erzwungen .. Allerdings, wenn ich das Formular und die Markenauflistung ablege auf der gleichen Seite verliere ich die ordentlichen Inline-Validierungsfehler, die bei fehlgeschlagenem Senden auftraten (siehe Bild unten). Nicht die Inline-Fehler zu bekommen in der Lage zu arbeiten hat mich gemacht klar, dass ich mehr lernen müssen, zu machen .. und das ist, warum ich bin fixiert auf der Suche nach der Antwort auf diese Frage

enter image description here

... und hier ist der Eintrag:

enter image description here

Unten ist der Controller für den Index Aktion:

def index 

    #This is for the product listing 

    @brands = Brand.all.reverse 

    #This is for the form 

    @brand = Brand.new 
    @model = Model.new 
    @submodel = Submodel.new 
    @style = Style.new 

    respond_to do |format| 
     format.html 
    end 
    end 

Die obige Form schafft die Marke, Modell, submodel und Stil für die Verwendung in dem verschachtelten Anmeldeformular ... Unten ist der Code für das Formular:

<%= simple_form_for @brand, :html => { :class => 'form-horizontal' }, :remote => true do |m| %> 

    <fieldset style = "margin-top:34px;"> 
    <legend></legend> 
    <%= m.input :name, :label => 'Brand' %>   
    <%= m.simple_fields_for :models, @model do |p| %>  
     <%= p.input :name, :label => 'Model' %> 
     <%= p.simple_fields_for :submodels, @submodel do |s| %> 
     <%= s.input :name, :label => 'Submodel' %> 
     <%= s.simple_fields_for :styles, @style do |ss| %> 
      <%= ss.input :name, :label => 'Style' %> 
     <% end %> 
     <% end %> 
    <% end %> 

    <div class="form-actions"> 
     <%= m.submit nil, :class => 'btn btn-primary' %> 
     <%= link_to 'Cancel', brands_path, :class => 'btn' %> 
    </div> 
    </fieldset> 
<% end %> 

Nun, wie Sie mich :remote => true bin mit sehen können .. Ich möchte, dass das Formular entweder die neue "Marke" erstellt oder das Formular mit Inline-Validierungsfehlern neu geladen wird. Im Moment Aktion eröffne meine wie folgt aussieht:

def create 
    @brand = Brand.new(params[:brand]) 

    respond_to do |format| 
     if @brand.save 
     format.html { redirect_to brands_url, notice: 'Brand was successfully created.' } 
     format.json { render json: @brand, status: :created, location: @brand } 
     format.js 
     else 
     format.html { render action: "index" } 
     format.json { render json: @brand.errors, status: :unprocessable_entity } 
     format.js { render 'reload' } 
     end 
    end 
    end 

Der Code, der unter if @brand.save scheint zu funktionieren scheint .. aber der Code unter „else“ funktioniert nicht, die Art und Weise Ich mag würde. Was passiert also, wenn @brand nicht speichert? Ich glaube, dass der Code innerhalb der Indexaktion ausgeführt wird, dann wird @ brand.errors in json konvertiert (was ich für die simple_form-Validierungsfehler halte), und dann wird reload.js.erb ausgeführt.

Beim Versuch, das Formular (mit Validierungsfehlern) neu zu laden, habe ich die Zeile $("#entryform").load(location.href+" #entryform>*",""); in reload.js.erb eingefügt ... Wenn ich ungültige Daten in mein Formular lege, wird reload.js.erb aufgerufen, aber alles was passiert, ist das Die Formularfelder werden nicht mehr neu geladen, sondern die Daten werden eingegeben und Validierungsfehler werden angezeigt.

Ich hoffe, ich habe genug Informationen hier zur Verfügung gestellt, um Hilfe zu bekommen .. Wirklich kämpfen auf diesem. Vielen Dank!

+0

Das ist * so * nahe bei dem, was ich versuche zu tun, aber ich bekomme es nicht zur Arbeit. Leider ist der in der Originalfrage verlinkte Guide weg. Wenn Sie 'simple_form_for' aufrufen, setzen Sie' "data-type" =>: json' nicht? Muss man im Controller sowohl 'format.json' * * als auch *' format.js' aufrufen? Und im JavaScript müssen Sie die '@ brand.errors' nicht als lokale Variable zurückgeben? Vielleicht ist es anders, weil ich ein Modal verwende. Ich habe eine neue Frage in der Hoffnung, um Klärung zu bekommen: [Anzeige Inline - Fehler mit Simple_form in einem Bootstrap Ajax Modal] (http://StackOverflow.com/q/13408508/550712) –

Antwort

30

Ich glaube, Sie dies in einem Teil, indem Sie Ihre Form vereinfachen können (wir werden es simple_form nennen), und diesen Code in reload.js.erb setzen:

$("#entryform").html("<%= escape_javascript(render :partial => 'simple_form') %>"); 

Ich bin nicht vertraut mit jQuery load Methode, aber ich nehme an, es tut eine zweite Anfrage. Der Schlüssel bei Rendering-Fehlern ist die Instanzvariable (@brand), die Sie beim Rendern des Formulars verwenden, die dieselbe ist, die Sie in create gespeichert haben, damit Sie die Fehler überprüfen können. Aus diesem Grund verwenden Sie immer render anstelle von redirect_to, wenn Sie Fehler rendern möchten.Wenn Sie eine Umleitung durchführen, starten Sie eine neue Anfrage, dh @brand wird neu initialisiert. Ich gehe davon aus, dass Ihr $(...).load(...) das gleiche Problem hat.

+2

Nicht nur haben Sie meine Frage (mit einem einfache Arbeitslösung) .. Sie haben auch eine gute Erklärung gegeben. Groß. – Abram

+0

Es kann ein Problem mit dieser Methode geben, wenn Sie Javascript an eines der Elemente im Formular angehängt haben, wird es nicht funktionieren, nachdem das Formular mit Fehlern gerendert wurde – JustMichael

+1

@JustMichael in diesem Fall Ereignishandler an Elternelemente anhängen, zum Beispiel anstelle von '$ ('# target'). on ('click', function (e) {...})' '' (Dokument) .on ('click', '#target', function (e) {...}) ' – Kote

0

Überprüfen Sie dies: Aufruf von .html (...) wird das Formular Wrapper div. Verwenden Sie .replaceWith (...) stattdessen =]

1

Danke für alle Q & A auf diesem. Es hat mich gerettet.

Simplify @tsherif Dateistruktur eine Kerbe (vorausgesetzt, Sie haben bereits eine js-Datei), löste ich dieses Problem mit dem Namen render direkt auf dem Formular und zeigt es über javascript/coffeescript.

#immediate_controller 
def action_with_modal 
    @brand = params[:failed_brand] || Brand.new 
end 

#brands_controller 
def create 
    @brand = Brand.new(params[:brand]) 

    respond_to do |format| 
    if @brand.save 
     ... 
    else 
     params[:failed_brand] = @brand 
     ... 
     format.js { render 'simple_form' } 
    end 
    end 
end 

#coffeescript 
$('form-selectors-here').on 'ajax:error', @reRegister 

reRegister: (e, data) => 
    $("div-that-contains-form").html(data.responseText) 
Verwandte Themen