I want to create a wizard in js.
steps :first_step,
:second_step
In my '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
I have problems after the update of the first step. I'm receive the following error message:
"Missing template controller_step/second_step, application/second_step with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}. ".
How can I force loading of js templete? I would load "second_step.js.erb".
I tried to change the update method:
respond_to do |format|
format.js { render :js => ( render_wizard @r ) }
end
Of course I get the following error:
"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"."
I also tried to change the code (in update):
respond_to do |format|
format.js { render :js => ( render_wizard @room_types and return ) }
end
I'm get the same error ( ... application/second_step with {:locale=>[:en], :formats=>[:html] .... )
P.S.
In view of the first step:
<%= form_for(@r, url: wizard_path, method: :put, remote: true) do |f| %>
....
<%= f.submit "Submit", class: "btn btn-default" %>
<% end %>
How do I fix ? thanks in advance
The #render_wizard
method defined in the Wicked::Controller::Concerns::RenderRedirect
is a wrapper method around the ActionController::Base#render
method. It
accepts a hash of options and passes it down to the controller's regular #render
method.
This is the source code from the Wicked library:
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
Your code:
respond_to do |format|
format.js { render :js => ( render_wizard @r ) }
end
is basically doing:
respond_to do |format|
format.js { render :js => ( render @r ) }
end
which is in fact calling the render method twice.
As it is searching for a .html
template rather than a .js.erb
one, try adding a formats: 'js'
option to the render_wizard method. It should prepend ['js'] to the :formats=>[:html]
we see in the Missing template
error message.
respond_to do |format|
format.js { render_wizard(@r, formats: 'js') }
end
also, make sure the template's filename follows the rails convention and start with a _
. (ie: _second_step.js.erb
)
About the double render error, you are correct. You must return from the controller #show
or #update
method and prevent further code from calling the #render
method a second time. You seem to have fixed that problem already.
EDIT#1
It seems like you may be able to call this method directly in your controller.. :
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
I believe the_step
will be the partial's name. I think you should be able to call the #render_step
method from your controller.
You may be able to do:
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