I am trying to rewrite a button_to - ruby-on-rails

I'm trying to rewrite the following button code so that instead of redirecting me to the show page, it just creates the object and the current page stays displayed.
<div class="colors">
<li class="colors" id="greys">
<%= button_to "some text", votes_path(color: 'grey', kid_id: current_kid, scoop_id: scoop.id, :method => :create), class: 'grey color-button' %>
</li>
</div>

You should use a remote flag to send the request via javascript. And possibly give feedback to the user.
To send a request via js in rails you have to add remote: true to the options hash:
<div class="colors">
<li class="colors" id="greys">
<%= button_to "some text", votes_path(color: 'grey', kid_id: current_kid, scoop_id: scoop.id, :method => :create), class: 'grey color-button', remote: true %>
</li>
</div>
In your controller you can do special responses by respondig to js
#votes controller
def create
# ...
respond_to do |format|
format.js render
end
end
In your create.js.erb you can write javascript code with embeded ruby to give responses. You can even render partials here.
alert('create.js.erb')

First, have some id for your button:
<%= button_to "some text", votes_path(color: 'grey', kid_id: current_kid, scoop_id: scoop.id, :method => :create), class: 'grey color-button' id: 'buttonID' %>
And then, in your Javascript code, whenever the button is clicked, send a request to server, create the new record, and then update the current page, so that it shows the record has been created.
I would show you the sculpture of how to do it:
$("buttonID").click(function() {
$.ajax({
url: "some_url" // Your URL, for example, /votes
type: "POST", // The type of request
data: { color: "grey" } // Send data to server in this format
success: function() {
// Here you can update the page so that the user could
// know the data has been posted, and no need to press
// the button again
}
});
});

Related

Rails 5: Send form via AJAX, modifying inputs first, and append a view to the form

(This question has been written to focus only on what is relevant.)
Within a page view I have a Rails form:
<%= form_for #model, url: {controller: 'foo', action: 'bar'} do |f| %>
<!-- various inputs -->
<%= f.button "Submit", type: 'submit' %>
<% end %>
When I click the 'Submit' button, I would like to:
Modify some of the inputs before sending
Send the form via AJAX
Replace the form with the view corresponding to the controller action (/views/foo/bar.html.erb)
What's the cleanest way to do this please?
1. Enable form submission via ajax using remote: true option
<%= form_for #model, url: {controller: 'foo', action: 'bar'}, remote: true do |f| %>
2. Modify inputs before form submit
$('form.model_name').on('ajax:beforeSend', function(event, xhr, settings) {
//Modify inputs
});
3. Replace the form with the view corresponding to the controller action (/views/foo/bar.html.erb)
In the action where the form is handled:
def create
....
.....
respond_to do |format|
format.js
end
end
4. create a .js.erb template where the other templates for this controller are placed
create.js
$('form.model_name').html("<%= j(render 'foo/bar.html.erb') %>")`
And that's it!

Update View After Destroying Item from Database

Right now I am displaying notifications for a user on a view. I have the ajax working where it removes the item from the database by clicking the close link. However, what I can't figure out is how to have the view update without actually refreshing the page.
Am I going to have to use a partial of some sort? I haven't really done anything like this and googling is really not helping me since I seem to be going down the rabbit hole.
Right now for my view I have:
<% current_user.notifications.each do |n| %>
<div class="alert alert-info">
<%= link_to 'x', n, :method => :delete, :remote => true, :class => 'delete_notification close' %>
<%= n.title %>
<%= n.description %>
</div>
<% end %>
and then I have my js:
$('.delete_notification').bind('ajax:success', function() {
$(this).closest('tr').fadeOut();
});
I'm not really sure how to ask the question since I am lost on what the 'next step' is. I will provide more information if/when I know what else I need to provide.
Thanks in advance!
UPDATE:
I accepted an answer seeing as it was extremely helpful and exactly what I was looking for!
What I ended up comming up with is:
$(function(){
$(".delete_notification").click(function(){
var $this = $(this);
var url = $this.data('url');
$.ajax(url, {
method: 'DELETE',
type: 'POST',
dataType: 'json',
success: function() {
var parent = $this.parent();
parent.fadeOut("slow");
}
});
});
});
The link_to's callback option (:update) is removed since Rails 3, so I'd rather implement the AJAX link myself.
<% current_user.notifications.each do |n| %>
<div class="alert alert-info">
<%= link_to 'x', n, :class => 'delete_notification close' %>
<%= n.title %>
<%= n.description %>
</div>
<% end %>
Setup AJAX so that it passes Rails' CSRF protection:
$.ajaxSetup({
beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))}
});
And finally the effect you want:
$('.delete_notification').click(function(ev) {
ev.preventDefault(); // prevent refreshing page
var $this = $(this);
var url = $this.attr('href');
$.ajax(url, {method: 'DELETE'}).done(function() {
$this.closest('tr').fadeOut();
});
});
Maybe you should also modify your controller (I haven't tested this):
class NotificationsController < ApplicationController
# Other actions ...
def destroy
# Your logic (remove rendering or redirection)
head :no_content
end
end
Create a js template in your view called destroy.js.erb, and in that file include the javascript you want to run - something like this:
$('#delete_notification_<%= params[:id] %>').closest('tr').fadeOut();
In your view make sure you specify the ID of the link:
<%= link_to 'x', n, method: :delete, remote: true, class: 'delete_notification close' id: "delete_notification_#{n.object.id}" %>

Responding with js in Rails

We have a link_to sending an ajax post, and are wondering if there's a way to change the content of the sending tag.
We basically want to update the database, then change the icon in the link_to block.
<%= link_to add_favorite_path({type: type, id: id}),
type:"button", disable_with: '...', :method => :post,
:remote => true, class: 'btn btn-default btn-sm', id: "#{type}-#{id}" do %>
<i class="fa fa-plus"></i>
<% end %>
Here's the favorites contoller:
class FavoritesController < ApplicationController
respond_to :js
def add
#type = params[:type]
#id = params[:id]
#selector = "#{#type}-#{#id}"
end
end
EDIT: add.js.erb:
var link = $("a#<%= #selector %>");
link.html('<i class="fa fa-check"></i>');
Found Solution:
Could not alter the item html when using the disable_with: option. Removed it and it works.
You can just make sure the appropriate controller reponds to JS
respond_to :js, :html
Then create the view file add.js.erb to add the appropriate JS to render the new icon.
I would like to see more code but something like this
$("#id_of_link").html("<i class='fa fa-check'></i>");
Although, I usually create partials and escape_javascript to render the new partial in the JS

How to Get value of text_field rails

I have a text field as:
<%= text_field :search, :class=>'input-xxlarge search-query',:id=>'keyword' %>
Then on click of a link I want to pass the value in this text field to a
controller method.
I do not want to use a form and form submit.
I have the link as:
<a href ="/home/search" >GO</a>
and to this 'search' method I want to pass the text field value....
also to go directly to the page "/home/search" designed to this action "search"
How do I do this???
Thank you...
Read here link_to send parameters along with the url and grab them on target page
<%= link_to "Go", '/home/search?param1=value' %>
So if you won't use form, you should use jQuery for put value of field into attribute link (href) with parameter.
Example on jsffidle
<%= text_field :search, :class=>'input-xxlarge search-query',:id=>'keyword' %>
<%= link_to "Go", '', :id => "searchlink" %>
$(':input').bind('keypress keydown keyup change',function(){
var word = $(':input[id="keyword"]').val();
$('a[id="searchlink"]').attr("href","/home/search?param1=" + word.toString());
});
and in controller:
if params[:param1] == ""
render :search # or redirect whatever do you want
else
param = params[:param1]
....
end
In your routes file
resources :home do
member do
get 'search'
end
end
In your html
<div id='parentDiv'>
<%= text_field :search, nil, :class=>'input-xxlarge search-query',:id=>'keyword' %>
<%= link_to("GO", '#', :class => 'search-link')
</div>
In the javascript file
$(document).ready(function(){
$('div#parentDiv').on('click', '.search-link', function(){
var search_val = $('#keyword').val().trim();
if(search_val != ''){
window.location.href='/home/'+search_val+'/search';
} else{
alert('You need to enter some data');
}
});
});
And in your search action
def search
search_value = params[:id]
# your code goes here.
end
Try something like this...(not tested). This will give you the logic.
<%= link_to "Go", "#", onclick: "window.location = \"www.sitename.com/home/search?q=\"+$(\"#keyword\").val()" %>

Rails change boolean value with checkbox and jquery ajax

I am new to rails and trying to change the value of a boolean via a checkbox and using jquery ajax:
<%- #tasks.each do |task| %>
<div class="task-wrapper">
<%= check_box_tag 'completed', task.id , task.completed, :class => "task-check" %>
<%= content_tag :span, task.task %>
<%= content_tag :span, task.deadline %>
</div>
<% end %>
and the javascript:
$(".task-check").bind('change', function(){
if (this.checked){
var bool = this.checked ? 1 : 0;
$.ajax({
url: '/todos/toggle',
type: 'POST',
data: '{"task_id":"'+ this.value +'", "bool":"'+ bool +'"}'
});
}
else {
alert("no");
}
});
then the controller:
def toggle(task_id, bool)
#task = Todo.find_by_id(task_id)
if #task != nil?
#task.update_attributes(:completed => bool)
else
set_flash "Error, please try again"
end
end
finally the routes:
resources :todos do
member do
post 'toggle'
end
end
also tried collection but gives the same error.
when ever i try it i get a 404 error on the action.
what is the problem?
thanks
As of Rails 4, there's a way to do this without needing any additional JS or CSS:
<%= check_box_tag 'completed', task.id, task.completed,
data: {
remote: true,
url: url_for(action: :toggle, id: task.id),
method: "POST"
} %>
It turns out that adding remote: true to an input causes jquery-ujs to make it ajax-y in all the nice ways. Thoughtbot's "A Tour of Rails jQuery UJS" briefly touches this (and many other good things available); the "Unobtrusive scripting support for jQuery" page in the jQuery UJS wiki does a thorough job on this as well.
Try the following (leaving everything else as is):
the javascript:
$(".task-check").bind('change', function(){
if (this.checked){
$.ajax({
url: '/todos/'+this.value+'/toggle',
type: 'POST',
data: {"completed": this.checked}
});
}
else {
alert("no");
}
});
the controller:
def toggle
#task = Todo.find(params[:id])
if #task.update_attributes(:completed => params[:completed])
# ... update successful
else
# ... update failed
end
end
Take a look at bundle exec rake routes to show you the paths that rails generates. In the case of your post 'toggle' which is a member you get a path like /todos/:id/toggle, hence the updated url in the ajax.
In the controller the :id from the path ends up in params[:id]. The data from the ajax request also ends up in the params hash, hence params[:completed].

Resources