Responding with js in Rails - ruby-on-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

Related

Creating a PUT request in Ruby on Rails?

I want to be able to use a PUT request to edit the title of a song I uploaded in my Ruby on Rails application.
def update
#sound_byte = SoundByte.find(params[:id]) #Error here
#sound_byte.update!(sound_byte_params)
flash[:success] = "The soundbyte title was changed."
redirect_to sound_byte_path
end
private
def sound_byte_params
params.require(:sound_byte).permit(:mpeg, :mpeg_file_name)
end
I end up getting an error like this:
Couldn't find SoundByte with 'id'=song_name
Any ideas of how to fix this issue? I am using the Paperclip gem to enable the audio/mpeg file uploads.
EDIT: Here is my views code
<%= link_to "Edit", sound_byte_path(sound_byte.mpeg_file_name), class: "btn btn-primary btn-lg btn-xlarge", :method => :put %>
In the view page, you pass string sound_byte.mpeg_file_name as params, but in your controller, you use id #sound_byte = SoundByte.find(params[:id]).
Try this
<%= link_to "Edit", sound_byte_path(sound_byte.id), class: "btn btn-primary btn-lg btn-xlarge", :method => :put %>

Rails button to disable if data is in database

I have a button that i need disabling if the data it was going to submit already exists in the database.
Bare in mind ive only been using this for like a month. so im a super noob!! haha!
The button is this <%= link_to 'Table', admin_table_statuses_path(table_id: #table.id), class: "btn btn-primary", method: :post, remote: true%>
my controller for this button is pretty basic also. see here
def create
table_id = params[:table_id] #Keep the same
#table_status = tableStatus.new
#table_status.table_id = params[:table_id]
#table_status.invoiced_out_user_id = current_user.id
#table_status.invoiced_out_datetime = DateTime.now
if #table_status.save
# Success
flash[:notice] = "Done!"
else
flash[:notice] = "Fail"
end
Give an ID to the button:
<%= link_to 'Table', admin_table_statuses_path(table_id: #table.id), class: "btn btn-primary", id: 'create_button',method: :post, remote: true%>
Inside create method do:
def create
.
.
.
render :update do |page|
if #table_status.save
page << "document.getElementById('create_button').setAttribute('href', '')"
end
end
end
Since, the element is a link not button, you can just remove it's href, so that it doesn't hit create method again.

How do I validate text_field_tag used for searching purpose in rails 4.1

In homepage/index:
<%= form_tag :controller => 'hotels', :method => 'get' do %>
<%= text_field_tag :search, nil, :class => 'search-box'%>
<%= submit_tag "Search", :name=>'btnsearch' %>
<%end%>
In hotels_controller:
def index
#hotels= Hotel.where('hotel_location LIKE ?',"%#{params[:search]}%")
I am new to Rails and I am wondering that how to validate text_field_tag for nil value.Means if no record was found, then display the error message without redirecting to the hotel/index page.
Your question is somewhat paradoxial:
If no record was found, then display the error message without
redirecting to the hotel/index page
What you're asking is to perform the functionality which can only be achieved after you've sent a request to your app, and then display the message without redirecting?
Ajax
You'll probably be best using Ajax (Asynchronous Javascript and XML):
This is a way of sending & receiving requests outside the scope of the typical "HTTP" request (IE without reloading the page). This sounds like what you're looking for, as it will ensure you're able to return the data you want without redirecting to your index view again.
The importance of Ajax is that it provides many HTTP developers with the ability to create much more "organic" interaction structures within their applications (IE not having to reload the page every time you want to do something)
Ajax is very simple to implement - I'd recommend it for you:
--
Search
Here's what I'd do:
#app/assets/javascripts/application.js
$(document).on("ajax:success", "#search", function(status, data, xhr){
$(this).append(data);
});
#config/routes.rb
...
resources :hotels do
get :search, on: :collection
end
#app/views/homepage/index.html.erb
<%= form_tag hotels_search_path, method: :get, id: "search", remote: true do %>
<%= text_field_tag :search, nil, :class => 'search-box'%>
<%= submit_tag "Search", :name=>'btnsearch' %>
<% end %>
This will send a "get" request to your hotels_search path - which will allow you to do the following:
#app/models/hotel.rb
class Hotel < ActiveRecord::Base
def self.search search
results = where('hotel_location LIKE ?',"%#{search}%") if search
if results
return results
else
return "No Records"
end
end
end
#app/controllers/hotels_controller.rb
class HotelsController < ApplicationController
respond_to :js, :json, :html
def search
#hotels = Hotel.search params[:search]
respond_with #hotels, layout: false
end
end
how to validate text_field_tag for nil. if no record was found, then display the error message without redirecting to the hotel/index page.
Looks like you need to validate it on client side. You can checkout bootstrap validator which is really nice for using validations on client side.
If you want to write your own js to handle it then you can do something like this:
$(document).on("click","#your_btn_id",function(e){
var textValue = $(this).closest(".search-box").val();
if(textValue == ""){
e.preventDefault();
alert("Please enter some value");
}
});
Update:
You can also utilize HTML5 validations and won't need any js
<%= form_tag :controller => 'hotels', :method => 'get', :validate=>true do %>
<%= text_field_tag :search, nil, :class => 'search-box', :required => true %>
<%= submit_tag "Search", :name=>'btnsearch' %>
<%end%>
If you don't want to use ajax then you can do:
def index
#hotels= Hotel.where('hotel_location LIKE ?',"%#{params[:search]}%")
if #hotels
#your action
else
flash[:notice] = "Please enter a valid value"
render 'your_form_action'
end
end
Since Rails generates HTML5, I am sure you can leverage its required attribute to have Search text box as a mandatory field on your view page. Like this:
<%= form_tag :controller => 'hotels', :method => 'get' do %>
<%= text_field_tag :search, nil, :class => 'search-box', :required => true %>
<%= submit_tag "Search", :name=>'btnsearch' %>
<%end%>
Just to be assured that your controller doesn't get nil in params[:search], you can change controller's index action with:
before_filter :validate_search, :only => [:index]
def index
#hotels = Hotel.where('hotel_location LIKE ?',"%#{params[:search]}%")
if #hotels.present?
# other operation here!
else
redirect_to :back # will work only when referrer is present!
rescue ActionController::RedirectBackError
redirect_to root_path
end
end
def validate_search
if params[:search].nil?
redirect_to root_path, notice: 'Enter few characters to search!'
end
end

Rails CRUD Buttons for all views using single Partial

Rails newbie here.
I would like to use a single partial to create my CRUD buttons on all views, regardless of controller. So this is what I have working so far. In my controller I have:
information_controller.rb
class InformationController < ApplicationController
before_filter :set
def set
#Set Paths
#new_path = new_information_path
#edit_path = edit_information_path
end
#Then normal index, show, etc definitions follows
end
I will take the index and edit pages as an example.
index.html.haml
-#operation = "index" #To let partial know what page it is in
-render 'form', operation: #operation
edit.html.haml
-#operation = "edit"
- render 'form', operation: #operation
Then, in my partial form I have:
_form.html.haml
.form-inputs
.container-fluid
.span8
.simple_form_for #foo do |f|
=f.input :title, as: :string
=render 'controls', f: f, operation: #operation
and in my controls form which serves only to display CRUD buttons regardless of the controller, I have:
_controls.html.haml
-if(operation=="new")
link_to "Create", #new_path, class: "btn btn-success"
-else
-if(operation=="edit")
=f.submit "Update"
-else
.span3
%table
%tr
%td=link_to "Edit", #edit_path(f), class: "btn btn-primary"
%td=link_to "Delete", f, confirm: "Are you sure", method: :delete, class: "btn btn-danger"
So this works well for the index page which loads 'edit, delete and create' buttons. But I do not know how I can properly assign edit_information_path in the controller to #edit_path because that requires an edit parameter 'f'.
The assignment #new_path = new_information_path works, but #edit_path requires 'f'. Any tricks?
Try this:
link_to "Edit",{:controller => params[:controller], :action => :edit, :id => f.object.id}, class: "btn btn-primary"
or:
link_to "Edit",{:controller => controller_name, :action => :edit, :id => f.object.id}, class: "btn btn-primary"

Getting callback from AJAX in Rails

In my index.html.erb I have a button like:
<%= button_to 'Test', question_path, :remote => true, :class => "btn btn-primary btn-large" %>
This triggers a method in my controller, which asks a server for a simple string value, and the method succesfully gets an answer back. This was verified by puts question.gets.
I want to pass that answer back to index.html.erb and show it in a <div>.
create an app/views/questions/show.js.erb and add the js code you need here.
# controller
def show
#question = ... # fetch question
end
# show.js.erb
$('#div_id').text('<%= escape_javascript #question.gets %>');

Resources