3

我在 Rails 应用程序中使用 Twitter Bootstrap 框架。我想要解决的是如何在窗口中呈现错误而不重新加载页面。

下面是一个例子:

#modalEvent.modal.hide
  .modal-header
    %button.close{"data-dismiss" => "modal", :type => "button"} ×
    %h3 Schedule Form
  = form_for(@schedule, :html => { :class => "form-horizontal"})  do |f|
    .modal-body
      - if @schedule.errors.any?
        #notice.alert.alert-error
          %button.close{"data-dismiss" => "alert"} ×
          %strong Error:
          = pluralize(@schedule.errors.count, "error")
          prohibited #{event_display(@schedule.event)} from being
          saved:
          %ul
            - @schedule.errors.full_messages.each do |msg|
              %li= msg
      .widget-content.nopadding
        .control-group
          = f.label :event_type, :class =>'control-label'
          .controls
            = f.select :event, Schedule::EVENT_TYPES
        #3{:style => 'display:none'}
          .control-group
            = f.label :name, :class =>'control-label'
            .controls
              = f.text_field :result_id, :class => "required error"
        .control-group
          = f.label :date_and_time, :class =>'control-label'
          .controls
            = f.text_field :time, :class => "datepicker", :required => :required, :type => :datetime, "data-date-format" =>"dd/mm/yyyy"
        .control-group
          = f.label :duration, :class =>'control-label'
          .controls
            .input-append
              = f.number_field :duration, :placeholder => 'Time in Minutes', :required => :required
              %span.add-on
                %i.icon-time
            %span.help-block Duration of event in minutes
        .control-group
          = f.label :arrival_time, :class =>'control-label'
          .controls
            .input-append
              = f.number_field :arrival_time, :placeholder => 'Time in Minutes', :required => :required
              %span.add-on
                %i.icon-time
            %span.help-block Time in minutes before event
        .control-group
          = f.label :location, :class =>'control-label'
          .controls
            = select("schedule", "location_id", Location.all.collect { |p| [p.name, p.id] }, {:include_blank => 'None'})
        .control-group
          = f.label :players, :class =>'control-label'
          .controls
            = select(:schedule, :selected_players, @players.map { |p| [full_name(p), p.id] }, {:include_blank => false}, "data-placeholder" => 'Add Players to Lineup', :prompt => 'Add Players to Lineup', :multiple => "multiple")
        #1{:style => 'display:block'}
          -if current_user.admin?
            .control-group
              = f.label :team, :class =>'control-label'
              .controls
                = select("schedule", "team_id", Team.all.collect { |p| [p.name, p.id] }, {:include_blank => 'None'})
          - else
            =f.hidden_field :team_id, :value => current_user.team_id
          .control-group
            = f.label :opponent, :class =>'control-label'
            .controls
              = select("schedule", "opponent_id", Opponent.all.collect { |p| [p.name, p.id] }, {:include_blank => 'None'})
          .control-group
            = f.label :home_or_away, :class =>'control-label'
            .controls
              = f.select :home_or_away, Schedule::HOME_OR_AWAY, {:include_blank => 'None'}
    .modal-footer
      = f.submit 'Save Event', :class => 'btn btn-primary'
      %a.btn.btn-danger{"data-dismiss" => "modal", :href => "#"} Cancel

控制器

def create
    @schedule = Schedule.new(params[:schedule])
    @user = User.find(current_user)
    @players = User.where(:team_id => current_user[:team_id]).all

    respond_to do |format|
      if @schedule.save
        Notifier.event_added(@user,@schedule).deliver
        format.html { redirect_to(schedules_url,
                                  :notice => "#{event_display_c(@schedule.event)} vs #{@schedule.opponent.name} was successfully created.") }
        format.json { render :json => @schedule, :status => :created, :location => @schedule }
      else
        format.html { render :action => "new" }
        format.json { render :json => @schedule.errors, :status => :unprocessable_entity }
      end
    end
  end
4

2 回答 2

2

如果您想避免页面重新加载并仍然显示服务器提供的错误消息,您必须以某种方式使用 AJAX。我认为仍然没有一种正确的方法可以做到这一点。您应该从谷歌搜索PJAX开始。你应该了解的另一件事是 Rails 提供了不显眼的 JavaScript

另外我建议您尝试一下simple_form gem,它与 AJAX 无关,但它会简化您的视图;)

于 2012-10-29T12:32:13.630 回答
0

我做了一些与此非常相似的事情,尽管使用 PHP/CodeIgniter 而不是 Rails,但为此我在模式窗口中使用引导程序。

我所做的是,在提交表单时,我将表单数据 ajax 到一个流程脚本,然后验证数据 - 如果验证失败,它返回(通过 JSON 对象)包含错误和可选错误消息的控制组类显示。如果验证成功,它将执行您希望执行的任何操作,并简单地返回一个“成功”标志,指示程序显示成功消息并关闭模式。

让我知道这个样本是否对你有用。如果是,我可以提供我执行的服务器端验证和输出的示例,尽管它不会在 ruby​​ 中。

这是一个示例表单,采用引导模式格式:

<div class="modal-header">
  <button type="button" class="close" data-dismiss="modal">&times;</button>
  <h3>Add Something</h3>
</div>
<div class="modal-body">
  <form id="your_form">
      <fieldset class="control-group id-group">
        <label>Some ID:</label><input type="text" name="SomeID" /><div class="clear"></div>
        <label>Another ID:</label><input type="text" name="Another ID" /><div class="clear"></div>
      </fieldset>
      <fieldset class="control-group category-group">
        <label>Category 1:</label><input type="text" name="Cat1" /><div class="clear"></div>
        <label>Category 2:</label><input type="text" name="Cat2" /><div class="clear"></div>
      </fieldset>
      <fieldset class="control-group description-group">
        <label>Description:</label><input type="text" name="Description" /><div class="clear"></div>
      </fieldset>
      <div class="clear"></div>
  </form>
  <div class="clear"></div>
  <div class="alert alert-error" id="addError">
  </div>
  <div class="alert alert-success" id="addSuccess">
  </div>
</div>
<div class="modal-footer">
  <a href="#" class="btn" data-dismiss="modal">Cancel</a>
  <a href="#" class="btn btn-primary" id="saveSomethingButton" data-loading-text="Please Wait...">Save</a>
</div>

这是我在提交表单时调用的 javascript 示例:

$("#saveSomethingButton").click(function() {

  //hide any previous errors should this be a second submit
  $(".alert").hide();
  $(".control-group").removeClass('error');
  $("input").blur();
  //set the save button to a "please wait" state to prevent double submission
  $("#saveSomethingButton").button('loading');

  //post to the validation script - if 
  $.post("<?php echo base_url();?>somecontroller/processfunction", $("#your_form").serialize(), function(data) {

    //if we were successful, show the happiness message and close the modal
    if (data.success == 1) {

      $("#addSuccess").html("<strong>Success! </strong> Something successfully added to database.");
      $("#addSuccess").fadeIn(300, function() {

        setTimeout(function() {

          $("#someModal").modal('hide');
        }, 2000);
      });
    //otherwise, highlight the problem fields and display the error
    } else {

      $("#addError").html("<strong>Error: </strong> "+data.message);
      $("."+data.fieldset).addClass("error");
      $("#addError").fadeIn(300);
      $("."+data.fieldset+":first input:first").focus();
    }
    //reset the button state so that they can correct errors and submit again
    $("#saveSomethingButton").button('reset');
  }, "json");

    //return false to prevent default form submission, which would reload the page
    return false;
});
于 2012-11-03T18:29:45.803 回答