According to the docs for Form Helper's form_for:
The form_for method automatically includes the model id as a hidden
field in the form. This is used to maintain the correlation between
the form data and its associated model. Some ORM systems do not use
IDs on nested models so in this case you want to be able to disable
the hidden id.
This makes sense and is important, but if you have two form_for calls on the same page, it generates two hidden fields with the same markup and the same id. In my case, it generates this twice on the same page:
<input id="clinic_patient_signup_clinic_patient_link_person_attributes_patient_information_attributes_id" name="clinic_patient_signup[clinic_patient_link][person_attributes][patient_information_attributes][id]" type="hidden" value="32" /></div>
Is there a way to overwrite the id attribute of that input? If I remember correctly, it's just the name attribute that is important, and the value can stay the same. Our site has to be WCAG 2.0 accessibility compliant, and it won't allow two tags on the same page with the same id. (That's also not valid HTML.)
Use the form_for :namespace option.
See https://stackoverflow.com/a/26415985/2511083 for a complete answer.
Related
Say I have the following q-input:
<q-input
v-model="form.email"
inverted-light
color="white"
stack-label="Email:"
type="email"
#blur="$v.form.email.$touch"
:error="$v.form.email.$error"/>
I'd like to be able to make it so that if the domain of the email is mydomain.com that the form action will change to another website (without csrf protection) and the POST will be made to that website instead of the main one.
To do this I was thinking I could use jQuery. eg. $('#email').val().replace(/^.+#/, '') == 'mydomain.com' then change the form action and submit.
The only problem is: I don't know how to set an id attribute on q-input.
Any ideas?
As of early Quasar 1.4.2 (November of this year) you can specify the id value on the resulting html generated by q-input by using the "for" property (see the end of the behavior properties: https://quasar.dev/vue-components/input#QInput-API).
So, for example, you could add for="myInputId":
<q-input
v-model="form.email"
inverted-light
color="white"
stack-label="Email:"
type="email"
#blur="$v.form.email.$touch"
:error="$v.form.email.$error"
for="myInputId"
/>
The id attribute with value "myInputField" will end up on the resulting <input> element in your HTML.
Not using the "for" in the elements gave me a lot of headaches because the Jest snapshot generated random IDs
Example, i made a form like this
<form name="register" method="post" enctype="multipart/form-data">
<p><h3>User check</h3></p>
<p>admin ID: <input type="text" name="userid"></p>
<p>admin Pass: <input type="password" name="password"></p>
<input type="submit" name="apply" value="Submit"></p>
<p> </p>
</form>
and my manager wants to change this form to rails form template like this,
<%= form_for(:model) do |form| %>
<p>
<%=form.label :input%>
<%=form.text_field :input, :placeholder => 'Enter text here...'%>
</p>
<%end%>
My question is, it works fine with html based front code. Why do i have to change this to rails code? I just want to keep my front-end code...I don't know why i have to change this :(. Also, I'm new on Ruby on Rails. That is the main reason. I dont' want to change the existing code, if it is working.
I really hate this job. I have to translate all the attributes to the rails code and that makes me really exhausted :(
Form builders are here to help
Form helpers are supposed to make your life simpler. They are quicker to write than their pure html alternative, provided you don't write pure html first.
They also provide a lot of easy implementations for difficult integration pieces, like :
displaying a date selection select group
mirroring the fact that a check box has been unchecked in POST params
automatically adding multipart param on form if you add a file input (not actually difficult to achieve, but easy to forget)
... and many more
Further development
All of this is about comfort, and you may think you could avoid it if you already have a perfectly working pure html implementation.
But what happen if someone later has to add a date select input in your form ? She will have to use the rails helper, since it saves a lot of time in controller part to set date in database. But she won't be able to leverage form builder, since you haven't used it.
Now, she has to choose between using a non builderdate_select tag mixed in pure html or ... to rewrite your form completely. As you may realize, mixing different styles is generally considered ugly, and we don't like ugly in ruby.
Security
Form tag helpers also provide an important security measure : CSRF protection. Every time you use a rails helper to create a <form> tag, it automatically adds an hidden input containing a secret key. That key has to be posted with form data to prove request originated from current website.
If you use plain html forms, you won't have this security. You could of course add the token manually using the correct method, but this would again be more time wasting than simply using form helpers.
Bottom line
The main problem is that you write pure html before using rails helpers - that is what is wasting time.
Some benefits of using Rails form helpers are:
Consistent naming of input elements names and ids
i18n support for labels
generated URL with form_for is less error prone
Better handling of checkboxes
Nice helpers like options_for_select
Less typing
That last ones might be my favourite: less typing.
In Rails, when you go to the edit action, it automatically pulls the information from the models and populates the form. If I had a CRUD that saves sensitive information, for example password or ssn, how can I filter the values so that it doesn't just show it in plaintext when editing the form?
I was going to change the value in the controller by setting it to ****, but the potential risk there is people may submit the form and it will update the SSN to ****.
I'm not referring to filtering the params so it doesn't show up in console (config.filter_parameters).
Changing the input field to type="password" should resolve your problem. Just don't set the fields in the controller if they are blank.
If you are using a form builder, change text_field to password_field.
Im quite new to Angular, so how Im approaching this might be entirely wrong, but some general advice on which direction to take with this would be much appreciated. More or less what I'm trying to do is use Angular to create new "Like" objects (similar to facebook 'likes'). They contain two values, user_id (which used to be set by rails as current_user.id via devise's helper method) and post_id.
My problems:
current_user is not accessible in Angular's ng-controller
You can't provide default input values directly into the form like so:
`
<input type="text" value="<%= current_user.id %>" ng-model="newLike.user_id" >
So more or less what I'm asking is, how could I manage to set default values of the inputs for user_id and post_id. I've come across recommendations for using ng-init, however, from everything I've seen it seems that this only allows setting default input values from the angular controller
EDIT:
It took shockingly long for it to dawn on me to pass the variables in as params to addLike so I've managed to successfully create new objects based off of the current_user.id & act.id.
Rails way
You can write inside your .html.erb (or .js.erb) javascript code that initializes a global / passes a parameter with the value of current_user.id
Angular way
Using ng-init is perfect here (better over the rails way). As Mark Rajcok commented ng-init can be used from your HTML like this:
<input type="text" ng-init="newLike.user_id='<%= current_user.id %>'" ...>
I want to create one form with 2 buttons in rails. Both forms operate on the same data in different ways, and I would prefer to keep the associated functionality in two different methods. Previously I've redirected to the appropriate method after doing a string comparision on params[:commit], but my gut says there's a better approach. Suggestions?
Two different submit buttons that send the form to two different actions:
<%= submit_tag('Insert', :onclick=>"document.myForm.action = 'insert';") %>
<%= submit_tag('Update', :onclick=>"document.myForm.action = 'update';") %>
Instead of "myForm" you need to put whatever is in the "name" property of your tag.
You can set that property in your default form:for tag like this:
<%= form_for(#something, :html => {:name => "myForm"}) do |f| %>
Without using JavaScript, your only solution is what you mention: checking which button was clicked by looking at the POST data in the controller. This is simply due to the nature of the HTML form element. It cannot have more than one value for its action attribute.
If you're not worried about what will happen when JavaScript isn't available, then you can write some script to change the action attribute when one of the submit buttons is clicked, prior to actually submitting the form. In the case of an ajax request, it could simply submit to the correct URL directly without altering attributes on the form.
I also used the params[:commit] method on a form already. Using the I18n helpers makes this a bit less fragile as you can use the same lookup in the view and controller, so you don't encounter the problem that the string changes a bit.
Besides that I can only think of using JavaScript to handle the clicks on the buttons and then send the form data to different Rails actions (Maybe you can change the HTML action attribute of the form with JavaScript before you submit the form).
If you're using prototype.js, you can use Form.serialize() to grab your data from your form and from there use the different buttons to post to different actions.