Vraag AJAX-formulier (met behulp van simple_form) met bewaarde foutvalidatie


Dit is misschien een van de moeilijkere vragen die ik heb gesteld, maar ik zit een paar dagen vast en ik dacht dat het het beste zou zijn om ondersteuning te krijgen van de meer ervaren rails-gemeenschap.

Ik werk aan een dummy-app die deze handleiding ongeveer volgt ... ajax / jQuery tutorial...

Mijn eigen aanpassingen maken, heeft de gids me geholpen om een ​​"merk" (inclusief geneste modellen "model", "submodel" en "stijl") aanleveringsformulier (met behulp van simple_form) en merkenlijst op dezelfde pagina te maken. Dit werkt perfect en de validatie (voor mijn modellen) wordt afgedwongen. Echter, wanneer ik het formulier en de merkvermelding op dezelfde pagina zet, verlies ik de nette inline-validatiefouten die op de indieningsfout zijn opgetreden (zie afbeelding hieronder). Niet in staat zijn om de inline-fouten te laten werken heeft me doen beseffen dat ik meer te leren heb over rendering .. en dat is waarom ik gefixeerd ben op het vinden van het antwoord op deze vraag

enter image description here

... en hier is de aanbieding:

enter image description here

Hieronder staat de controller voor de indexactie:

  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

Het bovenstaande formulier maakt het merk, model, submodel en stijl voor gebruik in de geneste indieningsformulier ... Hieronder is de code voor het formulier:

<%= 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 %>

Nu zoals je kunt zien, gebruik ik :remote => true ... Ik zou het formulier graag willen gebruiken om het nieuwe "merk" te maken of om het formulier te herladen met inline validatiefouten. Op dit moment ziet mijn actie eruit als:

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

De code die verschijnt onder if @brand.save lijkt te werken .. maar de code onder "else" werkt niet zoals ik zou willen. Dus wat gebeurt er wanneer @brand NIET opslaat? Ik geloof dat de code in de indexactie wordt uitgevoerd, waarna @ brand.errors wordt geconverteerd naar json (wat naar ik aanneem voor de validatiefouten van simple_form is), en dan wordt reload.js.erb uitgevoerd ..

In een poging om het formulier opnieuw te laden (met validatiefouten) heb ik de regel geplaatst $("#entryform").load(location.href+" #entryform>*",""); in reload.js.erb ... Wanneer ik ongeldige gegevens in mijn formulier stop, wordt reload.js.erb aangeroepen, maar het enige dat gebeurt is dat de formuliervelden leeg opnieuw laden, in plaats van dat de gegevens worden ingevoerd en inline validatiefouten.

Ik hoop dat ik hier genoeg info heb gegeven om hulp te krijgen. Echt worstelen met deze. Bedankt!


19
2018-04-07 01:44


oorsprong


antwoorden:


Ik denk dat je dit kunt vereenvoudigen door je formulier in een gedeeltelijke vorm te plaatsen (we zullen het noemen simple_form) en zet deze code in reload.js.erb:

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

Ik ben niet bekend met jQuery's load methode, maar ik neem aan dat het een tweede verzoek doet. De sleutel met renderfouten is de instantievariabele (@brand) die u gebruikt tijdens het renderen van het formulier moet hetzelfde zijn dat u probeerde te bewaren in create, dus u kunt de fouten erop controleren. Dit is de reden waarom je altijd gebruikt render in plaats van redirect_to wanneer u fouten wilt weergeven. Als u een omleiding uitvoert, start u een nieuw verzoek, wat betekent @brand wordt opnieuw geïnitialiseerd. Ik neem je aan $(...).load(...) heeft hetzelfde probleem.


30
2018-04-07 12:41



Bedankt voor alle vragen en antwoorden op deze. Het heeft me gered.

Vereenvoudig de bestandsstructuur van @ tsherif één greintje (ervan uitgaande dat je al een js-bestand hebt), ik loste dit probleem op door render rechtstreeks op het formulier te geven en het te tonen via 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)

1
2017-10-02 20:16



Controleer dit: calling .html (...) dupliceert de form wrapper div. Gebruik .replateWith (...) in plaats =]


0
2018-04-24 22:15