0

Is it possible to show the errors of the form in the flash messages in ajax? I want to show the errors of the form when is not possible to save a record due to unique field.

my index

<!--<p id="notice"><%= notice %></p>-->
<h1>Empresas</h1>
<style>
.container {
}

</style>
<div class="container">
  <div class="row">
    <div class="text-center">
      <!-- Button trigger modal -->
      <button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#mynewempresa">
        Nueva empresa
      </button>
    </div>
  </div>

  <br>
  <br>



  <table id="empresas" class="display"><!--el id empresas es de datatables referenciado en empresas.coffe y display class es una clase de datatables-->
  <thead>

    <tr><!--active es para sombrear la fila-->
      <th>Clave</th>
      <th>Empresa</th>
      <th>Acción</th>
      <th></th>

    </tr>
  </thead>
    <tbody id="container_empresas">
      <%= render @empresas %><!--carga todos los empresas-->
</tbody>


</table>
<!-- Modal create action -->
<%= form_for(@empresa, remote: true, html: {class: "form-horizontal formulario-validado-create"}) do |f| %> <!--ajax remote: true-->
  <div class="modal fade" id="mynewempresa" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
          <h4 class="modal-title" id="myModalLabel">Agregar empresa</h4>
        </div>
        <div class="modal-body">

          <div id="flash_messages_placeholder" >

           </div>

          <div class="form-group">
            <%= f.label :IdEmpresa, "Clave:", class: "control-label col-md-2 " %>
            <div class="col-md-3">
              <%= f.text_field :IdEmpresa, class: "form-control empresa_clave",autofocus: true, minlength: "1", required: "true"  %>
            </div>
              <%= f.label :Empresa, "Empresa:", class: "control-label col-md-2" %>
            <div class="col-md-5">
              <%= f.text_field :Empresa, class: "form-control empresa_empresa",minlength: "4", required: "true"  %>
            </div>
          </div>





        </div>

        <div class="modal-footer">
          <button type="button" class="btn btn-default" data-dismiss="modal" id="mynewempresaclose">Cerrar</button>
          <%= submit_tag "Crear", class: "btn btn-primary"%>
        </div>
      </div>
    </div>
  </div>
<%end%>
</div>

my controller

class EmpresasController < ApplicationController
  before_action :set_empresa, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_usuario!


  # GET /empresas
  # GET /empresas.json
  def index
    @empresas = Empresa.all
    @empresa = Empresa.new
    respond_to do |format|
      format.html
      format.csv { send_data @empresas.to_csv}
      format.xls #{ send_data @empresas.to_csv(col_sep: "\t") }
    end
  end

  def import
    Empresa.import(params[:file])
    redirect_to empresas_path, notice: "Sucursales importadas."
  end

  # GET /empresas/1
  # GET /empresas/1.json
  def show
  end

  # GET /empresas/new
  def new
    @empresa = Empresa.new
  end

  # GET /empresas/1/edit
  def edit
  end

  # POST /empresas
  # POST /empresas.json
  def create
    @empresa = Empresa.new(empresa_params)
    format.js { render 'shared/error_messages_js'}

    respond_to do |format|
      if @empresa.save
        format.html { redirect_to @empresa, notice: 'Empresa was successfully created.' }
        format.json { render :show, status: :created, location: @empresa }
        format.js {flash.now[:notice] = 'La Sucursal se ha creado de forma exitosa.'} #ajax


      else
        format.html { render :new }
        format.json { render json: @empresa.errors, status: :unprocessable_entity }
        format.js {flash.now[:alert] = 'Error al crear la sucursal.'} #ajax


      end
    end
  end

  # PATCH/PUT /empresas/1
  # PATCH/PUT /empresas/1.json



  def update
    respond_to do |format|
            ##use locals if multiple models
        ##add model errors
        flash.now[:error] = @empresa.errors.full_messages
        ##flash.now[:error] = @model.errors.full_messages.to_sentence

      if @empresa.update(empresa_params)
        format.html { redirect_to @empresa, notice: 'Empresa was successfully updated.' }
        format.json { render :show, status: :ok, location: @empresa }
        format.js {flash.now[:notice] = 'La Sucursal se ha actualizado de forma exitosa.'} #ajax


      else
        format.html { render :edit }
        format.json { render json: @empresa.errors, status: :unprocessable_entity }
        format.js {flash.now[:alert] = 'Error al actualizar la sucursal.'} #ajax


      end
    end
  end

  # DELETE /empresas/1
  # DELETE /empresas/1.json
  def destroy
    @empresa.destroy
    respond_to do |format|
      format.html { redirect_to empresas_url, notice: 'Empresa was successfully destroyed.' }
      format.json { head :no_content }
      format.js {flash.now[:notice] = 'La Sucursal se ha borrado de forma exitosa.'} #ajax


    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_empresa
      @empresa = Empresa.find(params[:idempresa])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def empresa_params
      params.require(:empresa).permit(:IdEmpresa, :Empresa)
    end
end

my application helper:

module ApplicationHelper
  ###application_helper.rb
   def flash_display
       Rails.logger.info "show flash message ajax======== "
     response = ""
     flash.each do |name, msg|
       msg=msg ###"<i class='fa fa-quote-left fa-border'></i>"+msg+"<i class='fa fa-quote-right fa-border'></i>"+"<button type='button' class='close' title='hide' data-dismiss='alert'><i class='fa-times-circle-o fa pull-right'></i></button>".html_safe
       response = response +
       content_tag(:div, msg, :id => "flash_#{name}",:class=>"alert alert-danger") do
           "#{msg}".html_safe
       end
     end
     flash.discard
     response
   end
end

##views/shared/error_messages_js.erb

$('#flash_messages_placeholder').html("<%= escape_javascript raw(flash_display) %>");
LuisC
  • 335
  • 1
  • 11
  • I think this will help you : http://stackoverflow.com/questions/23967390/rails-flash-notice-via-ajax# Cheers. – Erica Nov 02 '16 at 00:51
  • Please include a code snippet of your AJAX request, how you are rendering your form, your controller code, etc. If you are using server-rendered JavaScript (SJR) via a `create.js.erb` template, then you can definitely show errors on the page in the flash or inline by updating the DOM with JavaScript. – Carlos Ramirez III Nov 02 '16 at 02:41
  • Yes it is indeed. – makallio85 Nov 02 '16 at 03:55

1 Answers1

0

Yes..its possible..

firstly,create a helper method that can be used to show flash messages on the view.

 ###application_helper.rb
    def flash_display
        Rails.logger.info "show flash message ajax======== "
      response = ""
      flash.each do |name, msg|
        msg=msg ###"<i class='fa fa-quote-left fa-border'></i>"+msg+"<i class='fa fa-quote-right fa-border'></i>"+"<button type='button' class='close' title='hide' data-dismiss='alert'><i class='fa-times-circle-o fa pull-right'></i></button>".html_safe
        response = response + 
        content_tag(:div, msg, :id => "flash_#{name}",:class=>"alert alert-danger") do 
            "#{msg}".html_safe  
        end     
      end
      flash.discard
      response
    end

Secondly,In your controller code where you post data using remote=true,handle js response as shown below.

     respond_to do |format|
          ##use locals if multiple models
        ##add model errors
        ##flash.now[:error] = @model.errors.full_messages
        ##flash.now[:error] = @model.errors.full_messages.to_sentence
        flash.now[:error]="You cannot edit this Page"
        format.js { render 'shared/error_messages_js'}
       end

     ##views/shared/error_messages_js.erb
        $('#flash_messages_placeholder').html("<%= escape_javascript raw(flash_display) %>");

So,the above js.erb file will look for an empty placeholder to show flash messages.So your form must also have a placeholder

    ###_form.html.erb
    <form action="<%= post_data_path(current_user)%>" method="post" data-remote="true">
    <div id="flash_messages_placeholder" > </div>

    ##input fields/submit button goes here
   <%end%>

Hope it helps :)

Milind
  • 4,535
  • 2
  • 26
  • 58
  • Thanks for answer, but still not work, I updated my code with your changes, please take a look – LuisC Nov 03 '16 at 14:04
  • I have updated my controller code to set the flash first and then render the js file.check that out and let me know :) – Milind Nov 04 '16 at 00:19
  • with your change only show the message "You cannot edit this Page" but not show the errors when I put duplicate key. the file "error_messages" is a .js or _js? – LuisC Nov 04 '16 at 01:42
  • so instead of flash message..put the model.error in it..ti will show the errors...flash.now[:error] = model.errors.full_messages – Milind Nov 04 '16 at 07:31
  • I put a duplicate key but the message does not appear. in the console appears this: ActiveRecord::StatementInvalid (TinyTds::Error: Violation of PRIMARY KEY constraint 'PK_Empresas'. Cannot insert duplicate key in object 'dbo.Empresas'. The duplicate key value is (3000). – LuisC Nov 04 '16 at 20:58
  • Its a database constraint error where you are trying to create new record while creating unique keys...just rename that key..may be an id or title/name.. – Milind Nov 07 '16 at 01:01
  • yes indeed, But that message is the one I need, which shows that the primary key exists – LuisC Nov 14 '16 at 01:19