Rails - render :action to target anchor tag?
I'm looking to use render like so:
render :action => 'page#form'
I also tried this:
render :template => 'site/page#f开发者_如何学运维orm'
That didn't work either. The form on this particular page is at the very bottom, and if any errors occur on submission I'd hate for the user to be defaulted to the top of the page. I also need to use render (not redirect) because I need to retain the objects and their errors.
How can I render to target a specific anchor tag?
Believe I found a solution. For anyone else having this issue, pointing the form like so:
<%= form_tag '/page#form' do %>
Seems to have solved the problem.
Quick summary on bobthabuilda's answer, for those not-so-bright folks like myself who recently googled into that question and can't seem to get the trick.
First of all, abstracting from Rails, every basic HTML <form>
has an option to add anchor to the target page, and for this to work you basically leave the anchor in the 'action'
attribute, like this:
<form action="/contact#form" method="post">
...
</form>
That way, upon submit, your browser will use a /contact#form
request, which will throw you right to the specified anchor.
What we need to do now is simply make rails generate our form tag the correct way, as in example above. This will require us to modify our view in two possible ways.
If you use
form_tag
in your view, use it the way bobthabuilda suggested:<%= form_tag '/contact#form' do %>
Simple as that, you just tell rails to set action of our form to
/contact#form
If you use
form_for
, there is an:anchor
parameter, which goes into specified:url
like this:<%= form_for @message, :url => contact_path(@message, :anchor => 'form') do |form| %>
or like this (if you rely on
:action
):<%= form_for(@message, :url => { :action => "create" , :anchor => "form" }) do |form| %>
This way rails will create correct action for the HTML form, and will add our anchor at the end of it afterwards.
Use JavaScript to move the view to the right place. There's no way I know of to do otherwise.
<script>
window.location = window.location.href + "#form";
</script>
Untested, but I think this should work.
Use redirect_to so the the browser gets the heads-up to scroll to the anchor:
redirect_to :action => 'page', :anchor => 'form'
You can use unobtrusive jQuery and a data-attribute.
For example in my app I have a big form with, among the others, an "address" fieldset in which the user should:
- write his address and then
- hit a "check" button to display a little google map to see if the address he entered is correct.
Of couse after he its the "check" button I want to render the form again but with the ancor to this address fieldset, where the map is displayed.
This is my .erb template:
<fieldset id="address" data-preview="<%= params[:preview] ? true : false -%>">
<legend>Write you address here, then check it</legend>
<div class="field">
<%= f.text_field :address %>
<input id="preview-button" type="submit" name="preview" value="check">
</div>
</fieldset>
When the check button is hit, it will set params[:preview]
. In my controller, the create
action looks like this:
def create @obj = current_user.objs.new(params[:obj]) if params[:preview] # geocoding code, and then: render action: "edit" else #... end end
So the action edit will be rendered with params[:preview]
still defined, and this will set the #address fieldset data-preview to true. Namely, this line of HTML will be rendered:
<fieldset id="address" data-preview="true">
Now all I need to do is to fetch that information through javascript and if data-preview
is true
move window location to the #address
anchor. Here is my unobtrusive jQuery code:
$(function() { var preview = $("#address").data('preview'); if (preview == true){ window.location = window.location.href + "#address"; }; });
And that's it!
I'd suggest using jQuerys validate plugin. You could even implement your own form helpers that use jquery validate plugin depending on what object attributes you need to validate.
Of course it's more work, but I believe it would pay off in the future.
Other than that - use ajaxified submission and process error messages after response is received.
If you use JQuery, try to make some if condition that applies only after render and do this:
$('#anchor').get(0).scrollIntoView();
精彩评论