Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
78 views
in Technique[技术] by (71.8m points)

How to make work of ajax on rails forms and how to get validation errors from server?

I am trying to apply this rails tutorial to my project. I made create action works. I added some validation to my model file. Now, problem comes here. When i submit entry form, rails must give errors. In the normal html way i can see the errors. But this ajax style page i can't make it work.

When i'am sending empty form, i can't get full_message validation error.

enter image description here

My error on console

Started POST "/personels" for 127.0.0.1 at 2021-02-05 11:38:18 +0300
Processing by PersonelsController#create as JS
  Parameters: {"authenticity_token"=>"79VVfQ99zFbghWb7jMgjJzYb021qIeAQwte/XPCdSAEWF+SiC9gD11i4ZMoTJayPf+oZlJZplt6w8AwDmZ1+6g==", "personel"=>{"name"=>"", "surname"=>""}, "commit"=>"Create Personel"}
  Rendering personels/create.js.erb
  Rendered personels/_personel.html.erb (Duration: 0.7ms | Allocations: 1061)
  Rendered personels/create.js.erb (Duration: 0.8ms | Allocations: 1136)
Completed 500 Internal Server Error in 3ms (ActiveRecord: 0.0ms | Allocations: 2760)


  
ActionView::Template::Error (No route matches {:action=>"edit", :controller=>"personels", :id=>nil}, missing required keys: [:id]):
    2:         <td><%= personel.name %></td>
    3:         <td><%= personel.surname %></td>
    4:         <td><%= link_to 'Show', personel %></td>
    5:         <td><%= link_to 'Edit', edit_personel_path(personel) %></td>
    6:         <td><%= link_to 'Destroy', personel, method: :delete, data: { confirm: 'Are you sure?' } %></td>
    7: </tr>
  
app/views/personels/_personel.html.erb:5
app/views/personels/create.js.erb:2
app/controllers/personels_controller.rb:40:in `block (2 levels) in create'
app/controllers/personels_controller.rb:33:in `create'

I am not editing record but it seems to trying to go :action => "edit". I don't understand why it is like happens.

Personel Controller

def create
    @personel = Personel.new(personel_params)

    respond_to do |format|
      if @personel.save
        format.html { redirect_to @personels, notice: 'Personel was successfully created.' }
        format.js
        format.json { render :index, status: :created, location: @personel }
      else
        format.html { render :new }
        format.js   { render layout: false , personel: @personel}
        format.json { render json: @personel.errors, status: :unprocessable_entity }
      end
    end
  end

Personel Model

class Personel < ApplicationRecord
validates :name, :surname, presence: true
  belongs_to :journal_doc_analytic, optional: true

  def name_with_initial
    "#{name} - #{surname}"
  end
end

create.js.erb file

var personels = document.querySelector("#personels");
personels.insertAdjacentHTML("beforeend", "<%= j render(@personel) %>");

var personel_name = document.querySelector("#personel_name");
personel_name.value = ""

var personel_surname = document.querySelector("#personel_surname");
personel_surname.value = ""

var notice = document.querySelector("#notice");
notice.innerText = "Personel was successfully created."

setTimeout(function(){
  notice.innerText = "";
}, 2500);

_personel.html partial

<tr>
        <td><%= personel.name %></td>
        <td><%= personel.surname %></td>
        <td><%= link_to 'Show', personel %></td>
        <td><%= link_to 'Edit', edit_personel_path(personel) %></td>
        <td><%= link_to 'Destroy', personel, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>

index.html.erb of Personel

<p id="notice"><%= notice %></p>

<%= render 'form', personel: @personel %>
<h1>Personels</h1>
<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Surname</th>
      <th colspan="3"></th>
    </tr>
  </thead>

<tbody id="personels">
<%= render @personels %>
</tbody>
<br>
<%= link_to 'ORDER', personels_path(order: :asc) %>
<%= link_to 'ORDER desc', personels_path(order: :desc) %>

_form.html.erb Partial

Espacially i added this script to code below : ERROR <%= personel.errors.full_messages.first %>

<script>window.addEventListener("load", () => {
  const element = document.querySelector("#new-personel");
  element.addEventListener("ajax:success", (event) => {
    const [_data, _status, xhr] = event.detail;
    element.insertAdjacentHTML("beforeend", xhr.responseText);
  });
  element.addEventListener("ajax:error", () => {
    element.insertAdjacentHTML("beforeend", "<p>ERROR <%= personel.errors.full_messages.first %></p>");
  });
});</script>

<%= form_with(model: personel, id: "new-personel", local: false) do |form| %>
  <% if personel.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(personel.errors.count, "error") %> prohibited this personel from being saved:</h2>

      <ul>
        <% personel.errors.full_messages.each do |message| %>
          <li><%= message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label :name %>
    <%= form.text_field :name %>
  </div>

  <div class="field">
    <%= form.label :surname %>
    <%= form.text_field :surname %>
  </div>

  <div class="actions">
    <%= form.submit data: {disable_with: "Saving..."} %>
  </div>
<% end %>

Routes

personels GET    /personels(.:format)                                                                     personels#index
                                      POST   /personels(.:format)                                                                     personels#create
                         new_personel GET    /personels/new(.:format)                                                                 personels#new
                        edit_personel GET    /personels/:id/edit(.:format)                                                            personels#edit
                             personel GET    /personels/:id(.:format)                                                                 personels#show
                                      PATCH  /personels/:id(.:format)                                                                 personels#update
                                      PUT    /personels/:id(.:format)                                                                 personels#update
                                      DELETE /personels/:id(.:format)                                                                 personels#destroy
question from:https://stackoverflow.com/questions/66060528/how-to-make-work-of-ajax-on-rails-forms-and-how-to-get-validation-errors-from-se

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I found the solution. I added new partial is named:

** _error.html.erb **

<% if @personel.errors.any? %>
<div id="error_explanation">
  <h2><%= pluralize(@personel.errors.count, "error") %> prohibited this personel from 
being saved:</h2>

  <ul>
    <% @personel.errors.full_messages.each do |message| %>
      <li><%= message %></li>
    <% end %>
  </ul>
</div>
<% end %>

and updated my ** create.js.erb **

var errors = document.querySelector("#errors");
errors.replaceChildren("");

if (errors.childElementCount == 0){ 
errors.insertAdjacentHTML("beforeend", "<%= j render partial: '/personels/error' %>");
var notice = document.querySelector("#notice");
notice.innerText = "";
} else {
var notice = document.querySelector("#notice");
notice.innerText = "Personel was successfully created.";
}

var personels = document.querySelector("#personels");
personels.insertAdjacentHTML("beforeend", "<%= j render(@personel) %>");

var personel_name = document.querySelector("#personel_name");
personel_name.value = ""

var personel_surname = document.querySelector("#personel_surname");
personel_surname.value = ""

setTimeout(function(){
notice.innerText = "";
}, 2500);

Result is : enter image description here

My controller is same.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...