I have a form and I need to have 2 submit buttons. This seems like the only way I can think to do to accomplish what I want.
The goal is to use one form to send to one method and then possibly redirect to another method depending on the params passed because the functions will be different.
Form:
<%= form_for(:mass, url: mass_product_variant_category_path, method: :get, remote: true) do |mass| %>
<%= mass.submit "Update All", name: "All", class: "btn btn-light" %>
<%= mass.submit "Update Files", name: "Files", class: "btn btn-light" %>
<% #Stuff.each do |variant| %>
<%= check_box_tag 'store_variant_ids[]', variant.id %>
<% end %>
...
<% end %>
I tried: <%= submit_tag "Submit", name: "All" %>, also not working.
The html:
<input type="submit" name="File" value="Update Files" class="btn btn-light" data-disable-with="Update Files">
Controller:
def mass_product_variant_category
#stuff = Stuff.where(store_variant_id: params[:store_variant_ids])
if params[:commit] == "File"
redirect_to edit_multiple_stuffs_path(stuffs: #stuffs)
else
respond_to do |format|
format.js
end
end
end
The params that get passed are:
{..."mass" => {hidden_field: "int"}, "other_attributes" => ["int"]...}
This is due to using remote: true, but not sure why or how.
How can I pass through a param based on the submit form?
I've read other SO posts on this, but there are very few and none seem to have a good or any accepted answers. I also cannot use hidden_fields due to needing a redirect based on submit button used.
Is there a "Rails" way to do this without needing to add javascript or is that my only option?
I solved this by using a hidden_field_tag within the form that gets filled in based on the submit button used through an onclick. I can then check the hidden_fields param in the controller.
The "name" attribute maps to the name in the params hash. For this case you should do something like:
if params["File"]
# Something
elsif params["All"]
# Other thing
else
# Default
end
Related
I am trying to do two things:
With Ajax render Edit form when a user clicks on Edit link/button
Then after editing and they click on Update link/button, hide the form.
...but unfortunately, it didn't behave that way. It perfectly renders the form through Ajax but...
it renders the form on all of the rows.
after edit and you click update it doesn't hide the form.
Below is the code:
controller
before_action :set_clock_entry, only: [:edit, :update]
def edit
end
def update
respond_to do |format|
if #clock_entry.update(clock_entry_params)
format.js { flash.now[:notice] = 'Clock entry was successfully updated.' }
format.html { redirect_to #clock_entry, notice: 'Clock entry was successfully updated.' }
format.json { render :show, status: :ok, location: #clock_entry }
else
format.html { render :edit }
format.json { render json: #clock_entry.errors, status: :unprocessable_entity }
end
end
end
edit.html.erb
<h1>Editing Clock Entry</h1>
<%= render 'form', clock_entry: #clock_entry %>
<%= link_to 'Back', clock_entries_path %>
_form.html.erb
<%= simple_form_for clock_entry, remote: true do |f| %> # I am setting remote: true here
<%= f.error_notification %>
<%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %>
<div class="form-inputs">
<%= f.input :purpose %>
</div>
<div class="form-actions">
<%= f.button :submit, class: 'btn btn-primary btn-block btn-lg' %>
</div>
<% end %>
edit.js.erb
$('#edit-clock-entry a').hide().parent().append("<%= j render 'form', clock_entry: #clock_entry %>")
html edit link
<tr>
<td>
<div id="edit-clock-entry">
<%= link_to 'Edit', edit_clock_entry_path(clock_entry), remote: true %>
</div>
</td>
</tr>
This is the image - it renders on all ids
I give it all/dedicate it to #bkunzi01's comment under the post to the problem/question and that is what helped me solved it. So this is how I eventually solved it:
Error 1:
So according to what was suggested as I mentioned earlier, I had to redefine my edit.js.erb file to handle unique id of the edit in the row. So my edit.js.erb becomes:
$('#edit-clock-entry-<%= #clock_entry.id %> a').hide().parent().append("<%= j render 'form', clock_entry: #clock_entry %>")
Error 2:
I did not create update action with ajax and that made it behaved the way it behaved. So I created a file called update.js.erb to handle what happens when users hit the update button. So my update.js.erb becomes:
$('.refresh').bind('ajax:success', function () {
$(this).hide().parent();
})
So this is what I have now shown in the image
Log also shows the right record was updated
This fixed it for me.
I want to add confirmation modal when bank manager has to delete bank_employee without clients bank_employee.users = nil. If bank_employee has clients I want to render different modal - destroy_confirmation_modal. How to do it in a proper way? Where should I put if condition?
code snipped of
edit.html.erb
<div class="row">
<div class="col-sm-12 col-md-12 col-xs-12 text-center bank-employee__button-wrapper bank-employees-users-registration__registrations-submit--wrapper">
<%= t('.delete') %>
<%= f.submit t('.submit'), id: "formSubmit", class: "bank-employee__button bank-employee__button-submit"%>
</div>
</div>
<% end %> // this `end` comes from `form_for`
<%= button_to "", bank_employee_path(#bank_employee), method: :delete, form: {id: "bankEmployeeDestroyForm" }, class: "bank-employee__button-destroy" %>
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 text-center">
<%= link_to bank_employees_path do %>
<span class="bank-employee__back-button">
<%= image_tag "icon_back.svg", alt: "Back icon", class: ""%>
<%= t('.back') %>
</span>
<% end %>
</div>
</div>
</div>
<%= render "destroy_confirmation_modal" %>
I don't think I should update my controller method but maybe I'm wrong?
controller.rb
def destroy
authorize current_bank_employee
#bank_employee = find_bank_employee(params[:id])
if #bank_employee.users.any? && associated_bank_employees.present?
reassign_users_and_notify_bank_employee
elsif #bank_employee.users.any?
render :edit
else
#bank_employee.destroy
render :destroy_notice, locals: { old_bank_employee: #bank_employee, assigned: false }
end
end
EDIT
my routes.rb
resources :bank_employees, except: [:show], concerns: [:with_datatable] do
member do
get :confirm
end
end
rails routes showed me this path as confirm_bank_employee so I've changed if condition as follow
<% if #bank_employee.users.empty? %>
<%= button_to "", confirm_bank_employee_path(#bank_employee), form: {id: "bankEmployeeDestroyForm" }, class: "bank-employee__button-destroy", remote: true %>
<% else %>
<%= button_to "", bank_employee_path(#bank_employee), method: :delete, form: {id: "bankEmployeeDestroyForm" }, class: "bank-employee__button-destroy" %>
<% end %>
You need a different approach.
<% if #bank_employee.clients.empty? %>
<%= button_to "", bank_employee_confirm_path(#bank_employee), form: {id: "bankEmployeeDestroyForm" }, class: "bank-employee__button-destroy", remote: true %>
<% else %>
<%= button_to "", bank_employee_path(#bank_employee), method: :delete, form: {id: "bankEmployeeDestroyForm" }, class: "bank-employee__button-destroy" %>
<% end %>
now you need two things:
inside routes.rb create a collection for your blank_employee_confirm_path:
whatever setup you have, i assume you have some kind of blank_employees resources path:
resources :blank_employees do
member do
get :confirm
end
end
now, inside your controller you need to add the method confirm:
def confirm
## do whatever you want do to here
render :js
end
this will then head over to confirm.js
create a confirm.js.erb file inside your blank_employees view folder. To confirm this is working, you can add a console.log('it works') in it.
Once you have confirmed that it is working you can add the javascript code to the confirm.js.erb file:
$('#modal-body').html('<%= escape_javascript(render :partial => 'shared/your_confirmation_modal'%>');
with this setup, you need in your edit.html.erb file a <div id="modal-body"></div> that will take the modal. Also notice that in my example the confirmation modal is stored in "views/shared/_your_confirmation_modal.html". Change the path to your setup or create the exact path in order to make this work!
Notice that the "confirm" path is for the blank_employees that have no clients. The button will be only rendered when there is no client. All the other logic you had before for the blank_employees with clients stay the same. You don't need to change there anything. If you had any logic inside there for blank_employees without any clients, move the code to the confirm method.
One more thing: Make sure to add to your destroy method a render :js as well, and inside destroy.js.erb add the same kind of logic like inside confirm.js.erb, beside that you want to render the modal for blank_employees with clients. Your destroy.js.erb file should look something like this:
$('#modal-destroy').html('<%= escape_javascript(render :partial => 'shared/your_destroy_modal'%>');
Very important: Just like with the first modal, add a <div id="modal-destroy"></div> to your edit.html.erb file, otherwise it wont render the modal.
If something is unclear, let me know!
Greetings!
i'd like to make a like/dislike ability on my RoR application. How can i make it via Ajax-requests ?
dislike and like - are integer how can i make an Ajax-request, than i can send the data of what i want to increment either "like" or "dislike" counter in my methods
I have a table with posts :
#app/views/dashboard/view.html.erb
<table>
<%if #post.count!=0%>
<%#post.each do |p|%>
<%if !p.text.nil?%>
<tr>
<td><b class="margin"><h4><%=p.text%></b></h4></td>
<td>by <%=p.user.username%> </td>
<td><span class="glyphicon glyphicon-thumbs-up likeAction"><%= link_to p.like, dashboard_like_path, :remote => true, :id => 'likecount' %> </td>
<td><span class="glyphicon glyphicon-thumbs-down"><%= link_to p.dislike, dashboard_dislike_path, :remote => true, :id => 'dislikecount' %> </td>
<%end%>
<% end %>
<%else%>
There's no posts yet, but you can add <%=link_to "one", dashboard_posts_create_a_post_path%>
<%end%>
</table>
My js file
#app/views/dashboard/view.js
$('#likecount').text(#post.like);
$('#dislikecount').text(#post.dislike);
my methods in controller :
#app/controller/dahsboard_controller.rb
def like
#post.increment!(:like)
respond_to do |format|
format.html
format.js
end
end
def dislike
#post.increment!(:dislike)
respond_to do |format|
format.html
format.js
end
end
My dashboard.js in assets/javascripts
jQuery(function($) {
$("likeAction").click(function(){
$.ajax({
url: dashboard_like_path,
type: 'POST',
success: function(){
$('#linkcount').text(data);
}
error: function(error){
alert(error);
}
});
});
});
You already have Rails built-in AJAX functionality, so no need for calling $.ajax. Simply set remote: true on your link_to 'Like', ..., remote: true and respond with the same code you have in app/views/dashboard/view.js: format.js { render action: 'view' }
EDIT: As long as like and dislike are set as member routes on posts:
dislike_post POST /posts/:id/dislike(.:format) posts#dislike
like_post POST /posts/:id/like(.:format) posts#like
You will have a params[:id] (if you send one) to do something like #post = Post.find(params[:id]), if you share this code with show, like and dislike. You can create a set_post before filter, so you don't repeat yourself.
You'll probably want to look at a gem called acts_as_votable
This sets much of your model functionality up - allowing you to use the likes of #post.downvote_from #user2 etc. I'll let you look into that, as it's what you need in the backend I think.
In regards the front-end (especially Ajax), you'll have to set up a controller action, and then hit it with a JS request:
#config/routes.rb
resources :posts do
match :vote, via: [:post,:delete]
end
#app/controllers/posts_controller.rb
class PostsController < ApplicationController
respond_to :js, :html, only: :vote
def vote
if request.delete?
#downvote
elsif request.post?
#upvote
end
end
end
This will allow you to use the following:
#app/views/posts/vote.js.erb
$(".element").html("<%=j render partial: "post/vote_count", object: #post %>");
#app/views/posts/index.html.erb
<% #posts.each do |post| %>
<%= render partial: "post/vote_count", object: :post %>
<% end %>
#app/views/posts/_vote_count.html.erb
<% method = #post.liked_by(current_user)
<%= link_to post.likes, post_vote_path(post), method: :post, remote: true %>
--
The Ajax functionality is pre-built into Rails; you have to be wary of which controller action it's going to send you to, as well as the response given.
My above code uses the respond_to block to invoke the .js.erb response -- allowing you to perform some actions when you send your request.
I'm trying to add a coupon to my checkout page, using an AJAX request that validates the coupon and updates the price accordingly. However, on loading the checkout view I get the error message:
First argument in form cannot contain nil or be empty
referring to the line <%= form_for #actioncode, method: :post ... in the form where the coupon is entered. I've tried to follow the steps here. How should I adjust my code?
The set up: #actioncode refers to a model where the admin stores actioncodes. Coupon_code is not included in any model but refers to the value that a user enters in the form. Coupon_code should be checked against the Actioncode model (specifically the 'actioncode' column) if the value exists (validation) and if so update the price based on the value in the Actioncode model in the colum 'discount'.
The checkout view contains the following form:
<%= form_for #actioncode, method: :post, url: {action: "check_actioncode"}, remote: true do |f| %>
<%= f.text_field :coupon_code, :placeholder => "Enter your coupon" %>
<%= f.submit "Submit Coupon Code" %>
<% end %>
Routes:
post 'check_actioncode' => 'actioncodes#check_actioncode'
In the actioncodes controller I have:
def check_actioncode
#actioncode = Actioncode.find(params[:coupon_code])
respond_to do |format|
if !#actioncode.nil?
format.js {}
else
flash.now[:success] = "Action code not found or expired"
end
end
end
The organizations controller renders the checkout view:
def checkout
#organization = Organization.new(organizationnew_params)
if #organization.save
#organization.members.each do |single_member|
single_member.send_activation_email
end
#actioncode = Actioncode.new
#amount = 100.00
#currency = "EUR"
#description = #organization.id
#transaction_description = "My description"
#transaction_type = "S"
#hash = hash(#description, #amount, #currency, #transaction_type)
render 'checkout' # This renders the checkout view.
else
render 'new_premium'
end
end
Update: If I add #actioncode = Actioncode.new to the controller that loads the view, I get another error message undefined method 'coupon_code' referring to the 2nd line of the form. coupon_code is indeed a variable nowhere defined but it should simply be a temporary value that the user has entered and that is checked against the actioncode in the model for validation. How should I do this?
Change your form to:
<%= form_for #actioncode, method: :post, url: {action: "check_actioncode", :controller => 'actioncodes'}, remote: true do |f| %>
<%= f.text_field :actioncode, :placeholder => "Enter your coupon" %>
Change your controller to:
def check_actioncode
#actioncode = Actioncode.where(:actioncode => params[:actioncode][:actioncode]).first
respond_to do |format|
unless #actioncode.blank?
format.js {}
else
flash.now[:success] = "Action code not found or expired"
end
end
end
I am looking to update a url when a selection is made from a dropdown. I would like to have the query to be dynamic, here is the following code:
<select id="mySchool" onchange="this.form.submit()">
<% #schools.each do |school| %>
<option value="<%= school.id %>"><%= school.name %></option>
<% end %>
</select>
<%= link_to "Apply School", "schools/assign_users?user_id=#{#user.id}&school_id=", :class => "btn btn-primary", :type => "button" %>
Can anyone point me in the right direction?
This is not the best way to create select in rails. You should rather use rails select_tag helper like this:
<%= select_tag 'school_id', options_for_select(#schools.collect{ |s| [u.name, u.id] }), id: "mySchool" %>
I am looking to update a url when a selection is made from a dropdown.
I think instead of showing the link upfront you should show the link only when a user select a value from dropdown so your code should be something like this:
<%= select_tag 'school_id', options_for_select(#schools.collect{ |s| [u.name, u.id] }), id: "mySchool" %>
<div id="schoolLink"></div>
#_link.html.erb
<%= link_to "Apply School", "schools/assign_users?user_id=#{user.id}&school_id=#{school.id}", :class => "btn btn-primary", :type => "button" %>
Now make a route to which you want to send the ajax request to:
post 'selected_school/:id' => 'school#selected', as: "select_school"
write a js function which will send ajax request on changing values in dropdown
$(document).on("change","#mySchool",function(e){
var school_id = $(this).val();
$.ajax({
type: "POST",
url: "/selected_school",
data: {id : school_id }
});
});
Find school and user inside controller and then finally render link by js
#school_controller.rb
def selected
#school = School.find(params[:id]) # find school by the passed id
#user = current_user # your logic to find user
end
#app/views/school/selected.js
$("#schoolLink").html("<%=j render partial: 'link', locals: {user: #user, school: #school} %>");
For details checkout Working with Javascript in Rails