This is almost an identical question as was asked here: https://stackoverflow.com/questions/28571985/rails-remote-true-equivalent, but no one answered. I am hoping this doesn't mean that the question is impossible, though.
I have a page where a list of people can be dragged and dropped into bins. An assignment in a join table is automatically generated when they are dropped. I want the page to not re-load, though. In ruby, I would do this using remote: true, but the re-direct here happens in my javascript file. I believe everything is set up correctly, if only I could put remote: true at the end of my window.location.pathname line in the .js file.
z_game_sessions.js
app.gameSession = {
dragDrop: function () {
$('.groups-students').sortable({
tolerance:"pointer",
revert: true
});
$('.draggables').draggable({
connectToSortable: '.groups-students',
revert: 'invalid',
stop: function (e) {
var id = e.target.id;
var groupId = $(this).closest('ul').attr('id');
if (groupId) {
window.location.pathname = "game_sessions/add_player/" + groupId + "/" + id;
}
}
});
}
}
game_sessions_controller.rb
def add_player
#game_session = Group.find(params[:group_id]).game_session
GroupAssignment.assign(params[:group_id], params[:student_id], #game_session.id)
respond_to do |format|
format.js
end
end
add_player.js.erb
$("#new-group-form-container").html("<%= j(render partial: 'new_group_form', locals: {f: #game_session}) %>");
_new_group_form.html.erb
<%= f.simple_fields_for :groups do |ff| %>
<div class="mdl-cell mdl-cell--4-col mdl-shadow--4dp group-assignment-forms" id="group<%= "#{ff.object.id}" %>">
<h3>Group</h3>
Password: <%= ff.object.password %>
<%= ff.input :name, label: "Group Name", wrapper_html: { class: "mdl-textfield mdl-js-textfield mdl-textfield--floating-label" }, input_html: { class: "mdl-textfield__input" }, label_html: { class: "mdl-textfield__label" } %>
<%= ff.input :_destroy, as: :boolean, label: "Remove Group" %>
<h4>Students</h4>
<ul class="groups-students student-drag-area" id="<%= "#{ff.object.id}" %>">
<% ff.object.students.each do |student| %>
<li class="draggables" id="<%= student.id %>"><%= student.full_name %></li>
<% end %>
</ul>
</div>
<% end %>
First, it should be a POST request. Change your routes.
Second, make your controller return html and then just do an ajax request&assign that retuned html on success.
So instead of:
window.location.pathname = "game_sessions/add_player/" + groupId + "/" + id;
it should be something like:
$.ajax({
url: "game_sessions/add_player/" + groupId + "/" + id,
type: "POST",
success: function(data) {
$("#new-group-form-container").html(data)
}
});
Related
For some time now, I'm trying to generate a reservation form, where only available rooms are listed for the arrival and departure dates chosen in that same reservation form. Unfortunately, until now I didn't manage to do so.
I set out a question already on my previous attempt, without any success. => https://stackoverflow.com/posts/59083421/edit
I'm now trying to look for alternative ways to get there. For reference, please find my previous attempt below.
Previous attempt: general idea
Tried to send/receive an AJAX. Cannot reach the success stage, and the bug seem lie in the dataType the AJAX call is expecting/I'm sending (JS vs JSON). Unfortunately, I don't know how to solve this.
When I use format.js in my controller, I do not reach the success stage in my ajax call
when I use render json: {:rooms => #rooms} I do not reach my hotels/rooms_availability.js.erb file and subsequently am not able to insert my available rooms.
Previous attempt: code
reservations/new.html.erb
<%= simple_form_for [#hotel, #reservation] do |f|%>
<div class="col col-sm-3">
<%= f.input :arrival,
as: :string,
label:false,
placeholder: "From",
wrapper_html: { class: "inline_field_wrapper" },
input_html:{ id: "start_date"} %>
</div>
<div class="col col-sm-3">
<%= f.input :departure,
as: :string,
label:false,
placeholder: "From",
wrapper_html: { class: "inline_field_wrapper" },
input_html:{ id: "end_date"} %>
</div>
<div class="col col-sm-4">
<%= f.input :room_id, collection: #rooms %>
</div>
<%= f.button :submit, "Search", class: "create-reservation-btn"%>
<% end %>
script for reservations/new.html.erb
<script>
const checkIn = document.querySelector('#start_date');
const checkOut = document.querySelector('#end_date');
const checkInAndOut = [checkIn, checkOut];
checkInAndOut.forEach((item) => {
item.addEventListener('change', (event) => {
if ((checkIn.value.length > 0) && (checkOut.value.length > 0)){
checkAvailability();
}
})
})
function checkAvailability(){
$.ajax({
url: "<%= rooms_availability_hotel_path(#hotel) %>" ,
dataType: 'json',
type: "POST",
data: `arrival=${start_date.value}&departure=${end_date.value}`,
success: function(data) {
console.log('succes')
console.log(data);
},
error: function(response) {
console.log('failure')
console.log(response);
}
});
};
</script>
hotels_controller
def rooms_availability
hotel = Hotel.includes(:rooms).find(params[:id])
arrival = Date.parse room_params[:arrival]
departure = Date.parse room_params[:departure]
time_span = arrival..departure
#unavailable_rooms = Room.joins(:reservations).where(reservations: {hotel: hotel}).where("reservations.arrival <= ? AND ? >= reservations.departure", arrival, departure).distinct
#hotel_cats = hotel.room_categories
#hotel_rooms = Room.where(room_category: hotel_cats)
#rooms = hotel_rooms - #unavailable_rooms
render json: {:rooms => #rooms}
#respond_to do |format|
#format.js
#end
end
def room_params
params.permit(:arrival, :departure, :format, :id)
end
hotels/rooms_availability.js.erb
var selectList = document.getElementById('reservation_room_id')
function empty() {
selectList.innerHTML = "";
}
empty();
<% unless #rooms.empty? %>
<% #rooms.each do |room|%>
selectList.insertAdjacentHTML('beforeend', '<option value="<%= room.id %>"><%= room.name %></option>');
<% end %>
<% end %>
I am having trouble binding an ajax:error response to a form ID. Can someone point me in the right direction to solve this problem?
Here is the code.
<%= form_for #person,
html: {
id: '#person_form',
class: 'js_inline_validate'
},
data: { validate_url: validate_field_people_path },
remote: true,
url: people_path do |f| %>
<div class="form-group">
<div class='form-group-label'>
<%= f.label :first_name %>
</div>
<%= f.text_field :first_name,
:id => 'first_name',
class: 'js_new_person_frm_validate js_new_person_first_name' %>
<div class="text-error small">
<span>
<%= #person.errors.full_messages_for(:first_name).first if #person.errors[:first_name].any? %>
</span>
</div>
</div>
<div class="form-group">
<div class='form-group-label'>
<%= f.label :last_name %>
</div>
<%= f.text_field :last_name,
:id => 'last_name',
class: 'js_new_person_frm_validate js_new_person_last_name' %>
<div class="text-error small">
<span>
<%= #person.errors.full_messages_for(:last_name).first if #person.errors[:last_name].any? %>
</span>
</div>
</div>
<div class="form-group">
<%= f.submit "Create", data: { disable_with: false } %>
</div>
<% end %>
Controller
class PeopleController < ApplicationController
......
def create
#person = Person.new(create_params)
if(#person.save)
flash[:success] = "person created successfully"
redirect_to root_path
else
respond_to do |format|
format.html { render :action => 'new' }
format.any(:js, :json) {
render :json => { :error => #person.errors }, :status => 422
}
end
end
end
.....
end
CoffeeScript
$ ->
$("#person_form").on "ajax:error", (event, data, status, xhr) ->
alert "ajax:error!"
#do more stuff
The issue I cannot solve is this works as below when I use 'document', but I need this to be specific to my #person_form. And I get no response when I replace document with my form_id. Am I missing something simple here?
$ ->
$(document).on "ajax:error", (event, data, status, xhr) ->
alert "ajax:error!"
#do more stuff
Thank You!
I'm leaving this simple answer out here for anyone else who may run across this issue. Hopefully, it's this simple for the next person. It took me HOURS to track down the problem.
It turns out the error was happening because of a very simple mistake:
<%= form_for #person,
html: {
id: '#person_form', <= ERROR IS HERE!!
class: 'js_inline_validate'
},
data: { validate_url: validate_field_people_path },
remote: true,
url: people_path do |f| %>
The #person_form should have been person_form (excluding the pound sign). Just a very simple error in code I didn't catch when switching from script to ruby.
The global event handler would catch the ajax:error and execute the code properly. The pound sign in the identifier was preventing the proper registration of the local ajax event.
I am following section 4 (Server Side Concerns) to set up ajax on a page. I've copied the tutorial text completely (replacing the model names with my own) and it creates and saves my "Participants" record and refreshes the partial....but it posts this weird code below the just submitted form:
$("
\n\n Helper:sampleemail#sample.com \n<\/li>\n\n").appendTo("#participants");
This seems to be some sort of weird mash-up of my partial information and my creat.js. It's not really an error...just extra code.
Here's my code
class ParticipantsController < ApplicationController
def new
#participant = Participant.new
#participants = #participants.recently_updated
end
def create
#participant = Participant.new(participant_params)
respond_to do |format|
if #participant.save
format.html { redirect_to #participant, notice: 'Helper Invited!' }
format.js {}
format.json { render json: #participant, status: :created, location: #participant }
else
format.html { render action: "new" }
format.json { render json: #participant.errors, status: :unprocessable_entity }
end
end
end
_form.html.erb
<ul id="participants">
<%= render #participants %>
</ul>
<%= form_for(#participant, remote: true) do |f| %>
<%= f.label :email %><br>
<%= f.email_field :email %>
<%= f.submit 'SUBMIT' %>
<script>
$(document).ready(function() {
return $("#new_participant").on("ajax:success", function(e, data, status, xhr) {
return $("#new_participant").append(xhr.responseText);
}).on("ajax:error", function(e, xhr, status, error) {
return $("#new_participant").append("<p>Oops. Please Try again.</p>");
});
});
</script>
<script>
$(function() {
return $("a[data-remote]").on("ajax:success", function(e, data, status, xhr) {
return alert("The helper has been removed and notified.");
});
});
</script>
_participant.html.erb
<li >
<%= participant.email %> <%= link_to participant, remote: true, method: :delete, data: { confirm: 'Are you sure?' } do %>REMOVE<% end %>
</li>
create.js.erb
$("<%= escape_javascript(render #participant) %>").appendTo("#participants");
destroy.js.erb
$('#participants').html("<%= j (render #participants) %>");
It seems like you are both responding with a js.erb file and listening for the ajax:success event. You should only need to do one. Right now the ajax:success listener is appending the response to the form and the response is javascript code. Remove that listener and you should get the desired results.
I am currently working with the Acts_As_Votable gem in Ruby to use a Like link on each of my posts so that users can vote. I found a great answer on here that helped be do exactly that but I'm trying to figure out how I can use a heart icon image instead of the Like/Dislike text. I want the image to update without refreshing, just like the text links do but can't figure out the logic. Here is the current code I am using:
controllers/prides_controller.rb
def like
#pride = Pride.find(params[:id])
#pride.liked_by current_user
if request.xhr?
render json: { count: #pride.get_likes.size, id: params[:id] }
else
redirect_to #pride
end
end
def dislike
#pride = Pride.find(params[:id])
#pride.disliked_by current_user
if request.xhr?
render json: { count: #pride.get_likes.size, id: params[:id] }
else
redirect_to #pride
end
end
prides/show.html.erb
<div class="single-heart-this">
<% if current_user.liked? #pride %>
<span class="heart-icon-loved">
<%= link_to "Dislike", dislike_pride_path(#pride), class: 'vote', method: :put, remote: true, data: { toggle_text: 'Like', toggle_href: like_pride_path(#pride), id: #pride.id } %></span>
<% else %>
<span class="heart-icon">
<%= link_to "Like", like_pride_path(#pride), class: 'vote', method: :put, remote: true, data: { toggle_text: 'Dislike', toggle_href: dislike_pride_path(#pride), id: #pride.id } %></span>
<% end %>
<span class="heart-no" data-id="<%= #pride.id %>"><%= #pride.get_likes.size %></span>
<% end %>
</div>
javascript/pride.js.erb
# Rails creates this event, when the link_to(remote: true)
# successfully executes
$(document).on 'ajax:success', 'a.vote', (status,data,xhr)->
# the `data` parameter is the decoded JSON object
$(".heart-no[data-id=#{data.id}]").text data.count
return
javascript/prides.js.coffee
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/
$(document).on 'ajax:success', 'a.vote', (status,data,xhr)->
# update counter
$(".heart-no[data-id=#{data.id}]").text data.count
# toggle links
$("a.vote[data-id=#{data.id}]").each ->
$a = $(this)
href = $a.attr 'href'
text = '$a.text()'
$a.text($a.data('toggle-text')).attr 'href', $a.data('toggle-href')
$a.data('toggle-text', 'text').data 'toggle-href', href
return
return
Thanks for your help.
Try this?
Add: class: "Change_me" to your link
<%= link_to image_tag("Dislike.png"), dislike_pride_path(#pride), class: 'vote', method: :put, remote: true, data: { toggle_href: like_pride_path(#pride), id: #pride.id }, class: "change_me" %>
src: link_to image_tag with inner text or html in rails
In your coffeescript, change the image src
$(".change_me").attr 'src', '/like.png'
src: Rails 3.1 CoffeeScript/JQuery - How to change the source of an image in a div?
Hello guys i am trying attempt a dynamic select here. as soon as i select the customer his total value in the bill should come and get displayed in the text field tag.
the view
jQuery(document).ready(function(){
jQuery(".customerid").bind("change", function() {
var data = {
customer_id: jQuery(".customerid :selected").val()
}
jQuery.ajax({
url: "get_cust_bill",
type: 'GET',
dataType: 'script',
data: data
});
});
});
</script>
<div class ="customerid"><%= f.label :customer_id %>
<%= f.collection_select :customer_id, Customer.all, :id, :name, options ={:prompt => "-Select a Customer"}, :class => "state", :style=>'width:210px;'%></div><br />
<div class ="customerbill">
<%= f.label :total_value, "Total Value" %>
<%= render :partial => "customerbill" %>
js.erb file
jQuery('.customerbill').html("<%= escape_javascript(render :partial => 'customerbill') %>");
the customerbill partial
<% options = []
options = #cust_bill.total_value if #cust_bill.present? %>
<%= text_field_tag "total_value", options %>
in contoller
def get_cust_bill
#cust_bill = CustomerBill.find_all_by_customer_id(params[:customer_id]) if params[:customer_id]
end
I feel the problem lies in the partial, the way i am calling the options so can anyone guide me how to get the value in text field??? thank in advance.
From what I understand, total_value text field does not show anything. Could you try to output the value of options and check if it always has a value? I suggest you check out the documentation for the text_field_tag. Basically, it accepts three variables like this:
text_field_tag(name, value = nil, options = {})
i was using getJSON method....and i feel that can be used here. hope the followng works.
jQuery(document).ready(function()
{
jQuery(".customerid select").bind("change", function() {
var data = {
product_id: jQuery(this).val()
}
jQuery.getJSON(
"/controller_name/get_cust_bill",
data,
function(data){
var result = "";
res = parseFloat(a[1]);
jQuery('.price input').val(res);
});
});
});
controller
def get_cust_bill
#cust_bill = CustomerBill.find_all_by_customer_id(params[:customer_id]).map{|p| [p.price]} if params[:customer_id]
respond_to do |format|
format.json { render json: #cust_bill }
end
end
so no need of calling js. erb partial you can simply have
<div class = "price"><%= f.input :price, :label => 'Price', :input_html => { :size => 20} %></div><br/>
all the best :)