<%= form_tag('add_person', method: 'get') do %>
<%= label_tag(:name, 'Name') %>
<%= text_field_tag(:name) %>
<%= submit_tag 'Add new person' %>
<% end %>
<%= def add_person
if params[:name] == "John")
enter code here
else
enter code here
end
end %>
How do I make the submit button call the function add_person? I'm using Ruby/Rails
Calling one or more methods via submit button:
The form_tag helper determines the controller method to be called:
<%= form_tag('controller/controller_method', method: 'put') do %>
The submit_tag passes a value to the controller where it's evaluated.
<%= submit_tag "Add Person" %>
In the controller, you branch based on the value passed by your submit button:
def controller_method
if params[:commit] == "Add Person"
add_person
elsif params[:commit] == "Method 2"
method_2
elsif params[:commit] == "Method 3"
method_3
end
end
Calling method via arbitrary button
You probably have something like this at the bottom of your form:
<div class="actions">
<%= f.submit %>
</div>
which can be replaced with the button_to helper, like so:
<%= button_to "Submit", :method=> 'add_person' %>
Your add_person method would have to be defined in the controller for the object to which your form refers.
Related
I have an index where users can apply many different kinds of filters through checkboxes.
Each filter has an "X" link_to button that dismisses the filter, which basically makes a request to the same index page permiting the current params with the exception of the dismissed filter's param key.
For example:
<div class="form-group <%= 'hidden' unless params.dig(:q, "subscription_payment_type_eq").present? %>" id="subscription_payment_type_eq" data-toggle-target="objective">
<%= f.select :subscription_payment_type_eq, payment_types_selector_for_filter, { include_blank: "Forma de pago..."}, class: "form-control gray my-2 " %>
<% if params.dig(:q, "subscription_payment_type_eq").present? %>
<%= link_to admin_users_path(params: params.permit(q: [:extra_params, :address_province_eq, :subscription_status_eq, :created_at_gteq, :created_at_lteq])) do %>
<span class="dismiss-box glyphicon glyphicon-remove-circle">
<% end %>
<% end %>
</div>
<div class="form-group <%= 'hidden' unless params.dig(:q, "address_province_eq").present? %>" id="address_province_eq" data-toggle-target="objective">
<%= f.select :address_province_eq, user_provinces_selector_for_filter, { include_blank: "Provincia..."}, class: "form-control gray my-2 " %>
<% if params.dig(:q, "address_province_eq").present? %>
<%= link_to admin_users_path(params: params.permit(q: [:extra_params, :subscription_payment_type_eq, :subscription_status_eq, :created_at_gteq, :created_at_lteq])) do %>
<span class="dismiss-box glyphicon glyphicon-remove-circle">
<% end %>
<% end %>
</div>
The approach works, but it's very cumbersome to manually add the excepted param key to each new filter that is added to the index page.
Is there a way to pass params excluding the param key that belongs to the filter being dismissed?
I've tried the following but no params are passed:
<% if params.dig(:q, "subscription_payment_type_eq").present? %>
<%= link_to admin_users_path(params: params[:q].except(:subscription_payment_type_eq).permit) do %>
<span class="dismiss-box glyphicon glyphicon-remove-circle">
<% end %>
<% end %>
Also tried this but got undefined method 'exclude' for #<ActionController::Parameters:0x00007f6331b00dd8>
<%= link_to admin_users_path(params: params.exclude(:subscription_payment_type_eq).permit) do %>
Permit expects a list of args and since you're not sending any no params will be passed to your controller. I'm actually not sure how your calling permit without args is even working. Anyway maybe you can try it like this instead:
<%= link_to admin_users_path(params: params[:q].except(:subscription_payment_type_eq.permit!)
In the end we decided to implement it this way:
<%= link_to admin_users_path(
params: { q: params.require(:q).permit(params[:q].keys - ["address_province_eq"]) }
) do %>
We basically substract the filter's key from the current params when passing it in the link_to
I can send the param x=y in a form with a hidden field like this
<%= form_with(url: '/search', method: 'get') do %>
<%= text_field_tag(:query) %>
<%= hidden_field_tag(:x, 'y') %>
<%= submit_tag("Search") %>
<% end %>
Is it possible to send params in the URL? The following doesn't work
<%= form_with(url: '/search?x=y', method: 'get') do %>
<%= text_field_tag(:query) %>
<%= submit_tag("Search") %>
<% end %>
As you can read here, the query string that you might have in a HTML form action attribute will not taken into account.
Translated into your form_for problem, it means that the query string that you have in your url: are not taken into account.
Hence, your hidden_field_tag is the right solution for this problem.
Okey, so im kinda new to ruby on rails. Im trying to call a function when im pressing a button. But i have no idea how to do this.
This is basicaly what im trying to do:
<% button_to 'Ban User', call_this_function %>
<% this_function %>
#user = User.find(:id)
#user.deactivated("true")
<% end %>
Here is some actual code that I wrote
<% if has_role?(:admin) %>
<% if !#user.deactivated %>
<% if !#user.has_role?(:admin) %>
<%= link_to 'Ban User', new_discussion_path, class:"button is-danger" %>
<% end %>
<% else %>
<%= link_to 'Unban User', new_discussion_path, class:"button is-success" %>
<% end %>
<% end %>
But this only redirects to a page to where I can create a new discussion. What I'm trying to do is to just call a named function when impressing the button, but do not redirect to some other page. I'm sorry for the lack of code, but please ask if you need some clarification.
add a controller action to your corresponding controller like,
def ban_user
#user = User.find(params[:id])
#user.deactivated("true")
end
add this action to your routes.rb
get 'controller/ban_user'
now you can add the link to your views
<%= link_to 'Ban User', controller_user_ban_path(:id => #user.id), class:"button is-danger", remote: true %>
this will call the function without loading the page.
I have an app where Question model has_many relationship with Option. I also have a button to add options while creating a question. Every question has only one correct answer. So when I create a question and click on Add Option button, new option is created but the new radio button associated with it has different name. In fact the name of radio button is of the form question[options_attributes][i][is_answer] where i is id. As far as I know radio buttons should have the same name to work as a collection or group. So how can I make it work as a group even if I create any number of options for a single question?
html.erb
<%= form_for #question do |form| %>
<div class="field">
<%= form.label :body %>
<%= form.text_area :body %>
</div>
<%= form.fields_for :options, question.options.each do |a| %>
<div class="field">
<%= a.label :options %>
<%= a.text_area :body %>
<%= a.radio_button :is_answer, "options" %>
<%= a.check_box :_destroy %>
<%= a.label :_destroy, 'delete' %>
</div>
<% end %>
<%= form.submit 'Add option', :name => "add_option" %>
<%= form.submit 'Delete options', :name => "remove_option" %>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
controller.rb
class QuestionsController < ApplicationController
def new
#question = Question.new
#question.options.build
end
def create
#question = Question.new(question_params)
#question.user = current_user
if params[:add_option]
#question.options.build
else
respond_to do |format|
if #question.save
format.html { redirect_to #question, notice: 'Question was successfully created.' and return }
format.json { render :show, status: :created, location: #question }
else
format.html { render :new }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
render :action => 'new'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_question
#question = Question.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def question_params
params.require(:question).permit(:body, options_attributes: [:id, :body, :question_id, :created_at, :updated_at, :is_answer])
end
end
There are two options:
Using JavaScript on the client-side to uncheck the radio buttons.
Using radio buttons with the same name. It this case you will have to change the way you pass the :is_answer parameter and manually assign the value in options_attributes.
Method 1 details:
See this question radio different names - only check one
Method 2 details:
Instead of passing :is_answer parameter for each option you can pass a single parameter for the question having chosen answer id as the value. Lets name it "answer_id". We want this parameter to be in the params[question]
hash in the controller, so the whole name will be "question[answer_id]". Although radio buttons are generated for each option, only the chosen one will be sent to the server as they all have the same name.
<%= form.fields_for :options, question.options.each do |a| %>
<div class="field">
<%= a.label :options %>
<%= a.text_area :body %>
<%= radio_button_tag "question[answer_id]", a.object.id, a.object.is_answer? %>
<%= a.check_box :_destroy %>
<%= a.label :_destroy, 'delete' %>
</div>
<% end %>
https://apidock.com/rails/v4.2.7/ActionView/Helpers/FormTagHelper/radio_button_tag
In the controller you will have to manually assign the option's is_answer parameter based on the answer_id value.
def question_params
result = params.require(:question).permit(:body, :answer_id, options_attributes: [:id, :body, :question_id])
answer_id = result.delete(:answer_id)
result[:options_attributes].values.each do |option_attrs|
option_attrs[:is_answer] = option_attrs[:question_id] == answer_id
end
result
end
If you need further details please let me know. I will update the answer to give more information.
I am trying to access the value of an element in a different form. More specifically I have two forms, one normal html form which submits the information, and an ajax form that updates a field in the database. I want the ajax form to take the value of an element in the normal form, but I have no idea how to accomplish that. Here is my current setup:
Message View
<%= form_for #message do |f| %>
<%= f.text_field :to %>
<%= f.text_area :body %>
<%= f.submit "Send Message" %>
<% end %>
<%= form_for :save, :url => save_message_path(), :remote => :true do |f| %>
<%= f.submit "Save" %>
<% end %>
Message Controller
def save
account.message = params[:body]
end
But the :body param is in the other form so it sets account.message to nil because the ajax form did not have a body parameter. I would like it so the ajax form can submit the value of the body element.
Since the form is edited on the client side, you'll have to write this functionality in javascript.
It is relatively straightforward to copy the value of the message body into a hidden field and submit the Ajax form. This would be most easily accomplished by adding an id your ajax form as follows:
<%= form_for :save, :url => save_messages_path(), :remote => true, :id => 'ajaxform' %>
<%= hidden_field_tag 'hidden_message' %>
Then in javascript you could do the following:
$(document).ready(function(){
$("#ajaxform").submit(function() {
$("#hidden_message").val($("#message_body").val());
return true;
});
}
You can add a hidden field body in your ajax form, and use an onsubmit event to populate it with the value of the body field from the normal form before the ajax request is sent. It would look more or less like this:
<%= form_for #message do |f| %>
<%= f.text_field :to %>
<%= f.text_area :body, :class => 'main_body_field' %>
<%= f.submit "Send Message" %>
<% end %>
<%= form_for :save, :url => save_message_path(), :remote => :true, :id => 'ajax_form' %>
<%= f.hidden_field :body, :class => 'hidden_body_field' %>
<%= f.submit "Save" %>
<% end %>
javascript (with jQuery):
$(function() {
$("ajax_form").submit(function() {
// copy body value from first form to the second one
$('.hidden_body_field').val($('.main_body_field').val());
return true;
}
}