How exactly does Rails prefills forms? - forms

I have a (simple) question for my own curiosity:
I'd like to find out how Rails prefill forms with posted values like... you know, when there's a validation error on some models' attributes then you do something like "render :edit" and the form is magically prefilled.
What exactly are the mechanisms that Rails use to do such a thing? I didn't manage to find any documentation on this subject and I'd like to understand the magic.
So if someone can give me some explanations on this subject, I'll be glad to read that!
Thanks!
[Edit] And a subsidiary question: when a model inherits from another (STI) do we have to do something in particular to prefill forms?

You are mostly using the form_for helper in this style:
<%= form_for #person do |f| %>
<!-- Some more stuff here -->
<%= f.text_field :first_name %><br />
<!-- Some more stuff here -->
<% end %>
What this essentiall does is, it generates a text field that is filled with the value of #person.first_name.to_s. When an error happens, #person.first_name is filled with the errornous value. If you create a person (#person = Person.new), then #person.first_name.to_s is "".
So rails just fills the text field with the value, the attribute has.
f by the way is a rails FormBuilder. It's methods are documented here, if you want to take a closer look at the source.

Related

SilverStripe 3.1 custom form templating - how can I output a single action field without looping through all Actions?

Hello SilverStripe Community,
Forgive me if this is an elementary question, but in a custom form template, how can I output individual action fields without looping through all of them? Is there a way of doing that?
For example, when it comes to the form fields, I can loop through them with this:
<% loop $Fields %>
$Field
<% end_loop %>
OR I can output individual form fields like this:
$Fields.dataFieldByName(Email)
Is there something similar for form actions?
I know I can loop through them with:
<% loop $Actions %>
$Field
<% end_loop %>
but as I have one huge client form with several action buttons located in various positions in the form, I need to be able to output the action buttons individually with a great degree of control.
The only way I know how to achieve this at the moment is to manually create the markup for each action throughout the form, like this:
<button id="{$FormName}_action_doLogin" class="action button-login" value="Login" name="action_doLogin" type="submit">
<span>Login</span>
</button>
...but I'm looking for something like:
$Actions.dataFieldByName(Login)
OR
$Actions.Field(Login)
$Actions.Field(AddressLookup)
etc.
Does something like that exist in SilverStripe templating for Actions?
Thanks in advance.
all actions are prefixed with "action_"
so function
$Actions.dataFieldByName(Login)
works, but you need to call it as :
$Actions.dataFieldByName(action_Login)

select and onChange in a Ruby on Rails form

I browsed all SO questions and answers about this topic but I'm still unable to make my scenario work.
I want to trigger a click button action when a dropdown menu option is selected ; seems simple and should be very common with AJAX.
Here are the relevant excerpts of my code:
<%= form_for(#test, :html => {:id => "form_id", :name => "MyForm", :remote => "true"}) do |form| %>
<%= form.label "Menu1" %>
<%= form.select (:Menu1, [["Option1","value1"],["Option2","value2"]], :html_options=>{:onChange=>"javascript: this.form.apply_button_name.click();"}) %>
<!-- more select menus and text fields here -->
<div class="actions">
<%= form.submit "Apply", :name => "apply_button_name", :remote => "true" %>
</div>
<% end %>
I used ":remote => "true" both for the form and the button because that's the only way to get AJAX working. I also tried with and without explicit "html_options" and "javascript:", after I browsed some SO answers that suggested that but that did not help. I also tried onSelect, and onClick instead of onChange, but still no luck.
The generated HTML is the following:
Menu1
<select id="test_Menu1" name="test[Menu1]"><option value="value1">Option1</option>
<option value="value2" selected="selected">Option2</option></select>
As you can see, there's no onChange event handler in the HTML code ; WHY? Anyone is seeing what am I doing wrong?
Thanks for any help.
Modify your call to form.select, like this:
<%= form.select :Menu1, [["Option1","value1"],["Option2","value2"]], {},
:onChange=>"javascript: this.form.apply_button_name.click();" %>
If you examine the documentation for:
API Dock Ruby on Rails select
You will see that the select form helper takes the form:
select(object, method, choices, options = {}, html_options = {})
If you don't pass anything for the option hash (in your case this will be an empty hash), the form thinks that your html_options hash are your options hash, and gets confused.
A way to check this is to add something like {:onchange=> "alert('Hello');"} and either see if the event successfully triggers, or alternatively, in your actual web page, right click on the select element and inspect it. If no onchange option is present in the html, that means that your rails form helper is indeed confusing the html_options with the other options. So, what you should have:
<%= form.select (:Menu1, [["Option1","value1"],["Option2","value2"]], {}, {:onChange=>"handler();"} %>
MAKE SURE TO INCLUDE THE EMPTY HASH FOR THE OPTIONS BEFORE THE HTML OPTIONS AND YOU SHOULD BE FINE. I don't think you even need to have the html_options and javascript stuff you have.
Lastly, if onChange doesn't work, try to use onchange with no capital C.

ASP.NET MVC 2 and lists as Hidden values?

Hi,
I have a View class that contains a list, this list explains the available files that the user have uploaded (rendered with an html helper).
To maintain this data on submit I have added the following to the view :
<%: Html.HiddenFor(model => model.ModelView.Files)%>
I was hoping that the mode.ModelView.Files list would be returned to the action on submit but it is not?
Is it not possible to have a list as hiddenfield?
More information : The user submit a couple of files that is saved on the service, when saved thay are refered to as GUID and is this list that is sent back to the user to render the saved images. The user makes some changes in the form and hit submit again the image list will be empty when getting to the control action, why?
BestRegards
Is it not possible to have a list as hiddenfield?
Of course that it is not possible. A hidden field takes only a single string value:
<input type="hidden" id="foo" name="foo" value="foo bar" />
So if you need a list you need multiple hidden fields, for each item of the list. And if those items are complex objects you need a hidden field for each property of each item of the list.
Or a much simpler solution is for this hidden field to represent some unique identifier:
<input type="hidden" id="filesId" name="filesId" value="123" />
and in your controller action you would use this unique identifier to refetch your collection from wherever you initially got it.
Yet another possibility is to persist your model into the Session (just mentioning the Session for the completeness of my answer sake, but it's not something that I would actually recommend using).
Before I start I'd just like to mention that this is an example of one of the proposed solutions that was marked as the answer. Darrin got it right, here's an example of an implementation of the suggested solution...
I had a similar problem where I needed to store a generic list of type int in a hiddenfield. I tried the standard apporach which would be:
<%: Html.HiddenFor(foo => foo.ListOfIntegers) %>
That would however cause and exception. So I tried Darrin's suggestion and replaced the code above with this:
<%
foreach(int fooInt in Model.ListOfIntegers)
{ %>
<%: Html.Hidden("ListOfIntegers", fooInt) %>
<% } %>
This worked like a charm for me. Thanks Darrin.

MVC2 Custom HTML Helper and <%: %> Syntax

Is there any way to use a custom html helper with the <%: %> syntax ?
I know that if i'm use the code below, it's ok, but it's seems not so elegant and secure.
<%= Html.MyHelper("Some Data")%>
I mean, use <%= %> is the best practices?
Have your helper return an MvcHtmlString instead of a string. Also, please use <%: as much as possible.
HTML helpers create HTML, which is normally expected to be output raw with <%= %>. If you used <%: %> to HTML-escape the output of an HTML helper, you'll see the HTML source it produced on the page as text (eg literally <input name="foo" value="bar"> on-screen), which is probably not what you want.
It is up to the helper to HTML-escape any text content inside them, for safety. Yes, if you write a custom HTML helper and get it wrong—forgetting to HTML-encode strings your helper is putting in text content or attribute values in the output—you'll have security holes. You need to know what you're doing with escaping to write an HTML helper.
Microsoft, unfortunately, apparently don't, as the very first example in their tutorial completely fails:
return String.Format("<label for='{0}'>{1}</label>", target, text);
Whoops. Hope those ID and text strings didn't come from untrusted data!
[why are web tutorials always so lamentably terrible at escaping issues?]

How do I change the text_area default size for a form in rails 3?

I'm going through Agile Web Development with Rails and I'm having some trouble with the form helper text_area. Specifically, I want to make the text area smaller (the form submits correctly and everything goes into the database correctly). According to the book this code should work:
<%= form_for(#request) do |f| %>
<div class="actions">
...
<div class="field">
<%= f.label :quote_details, "*Items required:" %>
<%= f.text_area :quote_details, :rows=>5, :cols=>40 %>
</div>
It seems that no matter what numbers I put for :rows or :cols, the box stays the same default size. Instead of :rows and :cols, I used :size=>"3x40" and size=>"5x8" etc.. but the box still always stays the same size.
As an experiment I tried
<%= f.text_field :quote_details, :size=>"300*39" %>
That changed the number of columns, but removing the :size and putting :rows or :cols has no effect (it goes back to a default size for a text_field).
I did see this:
Change default Rails text_area helper rows/cols
I tried answer 1, but the answer given didn't work for me. I don't really understand what the second and third answers mean. I might be doing something else wrong or maybe it's a different problem.
I'm just stumped. Any help or ideas on what's going on would be greatly appreciated. Thanks for any responses.
Oh, I'm using rails version 3.0.0 and ruby 1.9.2p0 on vista.
your first code segment has :cols => 40% instead of 40?
I would also consider using CSS to do it, as that can make changing the look of the webpage isolated to the CSS presentation layer.
try do it with form_with. For me it works.
<%=form_with, local: true do |form| %>
<%= form.label :comment %>
<%= form.text_area :body, :rows=>10, :cols=>60 %>
<% end %>