Rails 邪恶的巫师 javascript

Rails wicked wizard with javascript

我想用js创建精灵

steps   :first_step,
        :second_step

在我的'controller_step'

def show
        case step
            when :first_step
                @r  = R.new
            when :second_step

            end
        render_wizard
end

def update
        case step
            when :first_step
                @r = R.new(r_params)
            when :second_step

            end

        render_wizard @r
end

第一步更新后出现问题。我收到以下错误消息:

"Missing template controller_step/second_step, application/second_step with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}. ".

如何强制加载js模板?我会加载 "second_step.js.erb".

我尝试更改更新方式:

respond_to do |format|
  format.js { render :js => ( render_wizard @r ) }  
end

当然我得到以下错误:

"AbstractController::DoubleRenderError in ...Controller#update Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return"."

我也尝试更改代码(更新中):

respond_to do |format|
   format.js { render :js => ( render_wizard @room_types and return ) } 
end

我遇到了同样的错误( ... application/second_step 与 {:locale=>[:en], :formats=>[:html] .... )

P.S.

鉴于第一步:

<%= form_for(@r, url: wizard_path, method: :put, remote: true) do |f| %>
   ....
   <%= f.submit "Submit", class: "btn btn-default" %>
<% end %>

我该如何解决?提前致谢

Wicked::Controller::Concerns::RenderRedirect中定义的#render_wizard方法是ActionController::Base#render方法的包装方法。它 接受选项的散列并将其传递给控制器​​的常规 #render 方法。

这是来自 Wicked 库的源代码:

def render_wizard(resource = nil, options = {})
  ...

  if @skip_to
    ...
  else
    render_step wizard_value(step), options
  end
end

def render_step(the_step, options = {})
  if the_step.nil? || the_step.to_s == Wicked::FINISH_STEP
    ...
  else
    render the_step, options #<-- Here
  end
end

您的代码:

respond_to do |format|
  format.js { render :js => ( render_wizard @r ) }  
end

基本上是在做:

respond_to do |format|
  format.js { render :js => ( render @r ) }  
end

这实际上是调用渲染方法两次。

因为它正在搜索 .html 模板而不是 .js.erb 模板,请尝试向 render_wizard 方法添加 formats: 'js' 选项。它应该将 ['js'] 添加到我们在 Missing template 错误消息中看到的 :formats=>[:html]

respond_to do |format|
  format.js { render_wizard(@r, formats: 'js') }
end

此外,请确保模板的文件名遵循 rails 约定并以 _ 开头。 (即:_second_step.js.erb


关于双重渲染错误,你是对的。您必须从控制器 #show#update 方法中 return 并防止进一步的代码再次调用 #render 方法。你似乎已经解决了这个问题。

编辑#1

看来您可以直接在您的控制器中调用此方法。:

def render_step(the_step, options = {})
  # Wicked::FINISH_STEP = "wicked_finish"
  if the_step.nil? || the_step.to_s == Wicked::FINISH_STEP
    redirect_to_finish_wizard options
  else
    render the_step, options
  end
end

我相信 the_step 将是部分的名称。我认为您应该能够从您的控制器调用 #render_step 方法。

你也许可以做到:

def show
  respond_to do |f|
    f.js do
      case step
      when :first_step
          @r  = R.new
          render_step(step) and return
      when :second_step
        ...
      end
    end
  end
end

我是这样解决的:

在 r 模型中:

validates   :x, presence: true

在步进控制器中:

...
steps   :first_step,
        :second_step,
        :finish_step
...

def show
    case step
        when :first_step
            @room_types  = R.new
        end

    render_wizard       
end

def update
   case step
      when :view_new_room_type_step
         @r = R.create(r_params)
      when :view_desc_step
         @r = R.find(params[:r][:id])
         @r.update(r_params)
      end

    respond_to do |format|
       if !@r.errors.any?
          format.js { !next_step?(:finish_step) ? ( render next_wizard_path ) : ( redirect_to_finish_wizard ) }
       else
          format.js { render wizard_path, r: @r }
       end
    end
end 

private
        ...

        def redirect_to_finish_wizard
            redirect_to r_index_path , notice: "Ok"
        end

在first_step.js.erb

$("#modal").html("<%= escape_javascript(render 'form_first_step') %>")

在_form_first_step.html.erb中:

<% if @r.errors.any? %>
   <div class="alert fade in alert-danger alert-dismissable"><button aria-hidden="true" class="close" data-dismiss="alert" type="button">&#215;</button>
      <ul>
         <% @r.errors.full_messages.each do |msg| %>
            <%= content_tag :li, msg, :id => "error_#{msg}" if msg.is_a?(String) %>
          <% end %>
      </ul>
    </div>
<% end %>

<%= form_for(@room_types, url: wizard_path, method: :put, remote: true) do |f| %>
   ...
<% end %>

第二种形式(第二步):

<%= form_for(@room_types, url: wizard_path(:second_step), method: :put, remote: true) do |f| %>
    ....
    <%= f.hidden_field :id %>
<% end %>

想法:验证步骤中的数据可以使用 jquery-form-validator-rails