I have a view with several "Invite" buttons like this:
<div class = "fbinvite_form" id = "<%= friend[:identifier] %>" name = "fb">
<div class = "btn btn-small">
Invite
</div>
</div>
When one of these buttons are clicked an AJAX function is called (invite_friend) :
$('.fbinvite_form').click(function() {
invite_friend();
});
Here's invite_friend (some values are hard-coded as I debug):
function invite_friend() {
$.post('/groups/7/invitations',
{
"recipient_email": "facebook#meetcody.com",
"commit" : "fb",
"fb" : "fb"
},
function(response) {
});
}
Here's the relevant line that is returned from the controller:
render :json => {
:url => signup_with_token_url(#invitation.token),
:id => #invitation.id
},
:status => :created
I can confirm that this json is being rendered correctly. At this point I'm expecting an ajax:success event to fire. I have the following code at the top of my page:
$('.fbinvite_form').bind("ajax:success", function(evt, data, status, xhr) {
...
});
But it's not firing. Any clue what might be going wrong or how to better troubleshoot (I'm a bit of a noob)?
Additional Context
I wanted to add a little bit more as it might help. I had originally built this to work with a form and it worked fine. For some performance reasons I decided to switch to buttons with AJAX. Here's the original form:
<%= form_for([#group, #invitation], :remote => true, :html => { :'data-type' => 'html', :class => 'fbinvite_form', :id => friend[:identifier]}) do |f| %>
<%= f.hidden_field :recipient_email, :value => "facebook#meetcody.com" %>
<div class = "fbinvite btn_list_right" id = "<%= friend[:identifier] %>">
<%= f.submit "Invite", :class => "btn btn-medium btn-primary", :name => "fb" %>
</div>
<% end %>
This has since been replace with all the code you see above the controller snippet.
UPDATE 1
Per Vince's suggestion I have moved the "ajax:success" code into the success function. Here is the original "ajax:success" function:
$('.fbinvite_form').bind("ajax:success", function(evt, data, status, xhr){
var fb_id = $(this).attr('id');
var response = eval("(" + xhr.responseText + ")");
var link_url = response.url;
var id = response.id;
var inv_url = <%= raw('"' + group_url(#group) + '/invitations/"') %> + id;
var picture_url = "https://www.example.com.com/assets/cody_130by130.png";
var desc = <%= raw('"' + first_name(current_user) + " is working with Cody on fitness. Join " + genderizer(current_user, "his") + " group to start tracking your workouts. Cody and the other group members will keep you motivated!" + '"') %>;
send_invite(fb_id, link_url, picture_url, desc, inv_url); return false;
});
And here is what I've done to move the code into the success function. The issue is that I don't seem to have access to "xhr"
$.ajax({
type: "POST",
url: "/groups/7/invitations",
data: {recipient_email: "facebook#meetcody.com", commit : "fb", fb : "fb" },
dataType: "json",
success: function(evt, data, status, xhr) {
var fb_id = $(this).attr('id');
var response = eval("(" + xhr.responseText + ")");
var link_url = response.url;
var id = response.id;
var inv_url = <%= raw('"' + group_url(#group) + '/invitations/"') %> + id;
var picture_url = "https://www.meetcody.com/assets/cody_130by130.png";
var desc = <%= raw('"' + first_name(current_user) + " is working with Cody on fitness. Join " + genderizer(current_user, "his") + " group to start tracking your workouts. Cody and the other group members will keep you motivated!" + '"') %>;
send_invite(fb_id, link_url, picture_url, desc, inv_url); return false;
}
});
Add error handler like this and log the error, this should help diagnose the issue.
error: function(xhr, status, error) {
console.log(error);
}
EDIT
Sorry you need to use .ajax instead of .post.
$.ajax({
type: "POST",
url: "/groups/7/invitations",
data: "name=John&location=Boston",
success: function(msg){
alert( "Data Saved: " + msg );
},
error(xhr, status, error) {
console.log(error);
}
});
Related
I have this javascript in my view
What can I do to fix this error?
<%= javascript_tag do %>
$("#check_module").click(function () {
IMP.init('imp45233'); //iamport 대신 자신의 "가맹점 식별코드"를 사용하시면 됩니다
IMP.request_pay({
merchant_uid : "<%= #merchant_uid %>",
name : '결제테스트',
amount : <%= #course.price %>,
buyer_email : '<%= current_user.email %>',
buyer_name : '<%= current_user.name %>',
buyer_tel : ' no phone ',
buyer_addr : ' course name: no address',
buyer_postcode : ' no postcode ',
m_redirect_url: ""
}, function(rsp) {
if ( rsp.success ) {// Successful payment: Successful payment approval or issuance of a virtual account
window.location.href= "<%= add_enrollment_path(:course_id => #course) %>"?imp_uid=rsp.data.imp_uid&merchant_uid=rsp.data.merchant_uid;
} else {
var msg = '결제에 실패하였습니다.';
msg += '에러내용 : ' + rsp.error_msg;
alert(msg);
}
});
});
<% end %>
I'm having problem with this line
window.location.href= "<%= add_enrollment_path(:course_id => #course) %>"?imp_uid=rsp.data.imp_uid&merchant_uid=rsp.data.merchant_uid;
After fixing the error with the suggestion below :
window.location.href= "<%= add_enrollment_path(:course_id => #course) %>?imp_uid=" + rsp.imp_uid + "&merchant_uid=" + rsp.merchant_uid;
Now I am running into a different problem: I think it is related to my route:
get 'enrollments/add_enrollment/', :to => 'enrollments#add_enrollment', :as => 'add_enrollment'
Here is the error
can't find record with friendly id: "reading-starter-01?imp_uid=imp_376842875552"
do I need to add /:course_id/ ?? I will try ^^ wish me luck
Try building the string properly:
"<%= add_enrollment_path(:course_id => #course) %>?imp_uid=" + rsp.data.imp_uid + "&merchant_uid=" + rsp.data.merchant_uid;
I'm new at RoR and I'm having a trouble in my app. The problem consists on filter a select field named "Solution", based on the others select fields above it.
Now, what the app do is to retrieve all information from BD about Area, Region, Associated, Solution and populate the select fields with these data. But the user wants that, when an area, a region and an associated is selected by the user, only the solutions about that associated in that region on that area should be shown.
Edit:
I'm almost there! I've made many changes in my app. The select fields are populated by controller action new and the function "populate_selects", which is called by the parameter before_action :popula_selects, only: [:new, :edit]. A new function was created in order to be called by AJAX and upgrade the "Solution" field:
Atendments_Controller < ApplicationController
before_action :populate_selects, only: [:new, :edit]
def new
#atend = atendment.new
end
def update_solution #AJAX
#solutions = atendment.joins(:solution).where("atendment_area_id = ? and atendment_region_id = ? and atendment_assoc_id = ?", params[:atendment_area_id], params[:atendment_region_id], params[:atendment_assoc_id])
respond_to do |format|
format.js
end
end
private
def populate_selects
#atendment_area = atendmentArea.where(status: true, user_id: current_user.id)
#atendment_region = atendmentRegion.where(status: true, user_id: current_user.id)
#atendment_assoc = atendmentRegionAssoc.where(status: true, assoc_id: current_user.entidade_id).where(atendment_region_id: #atendment_region.map(&:atendment_region_id))
#solutions = atendment.joins(:solution).where("atendment_area_id = ? and atendment_region_id = ? and atendment_assoc_id = ?", params[:atendment_area_id], params[:atendment_region_id], params[:atendment_region_assoc_id])
end
end
Below, the _form.html.erb code from view:
<div class="atendment-form">
<%= form_for :atendment, url: {action: "new"}, html: {method: "get"} do |f| %>
<div class="col-xs-6">
<%= f.select :atendment_area_id, options_for_select(#atendment_area.collect { |c| [ c.atendment_area.name, c.id ] }, 1), {:prompt=>"Área"}, { :class => 'form-control', :required => true, id: 'atendment_atendment_area_id' } %>
</div>
<div class="col-xs-6">
<%= f.select :atendment_region_id, options_for_select(#atendment_region.collect { |c| [ c.atendment_region.name, c.id ] }, 1), {:prompt=>"Região"}, { :class => 'form-control', :required => true, id: 'atendment_atendment_region_id' } %>
</div>
</div>
</div>
<div class="field">
<%= f.select :atendment_assoc_id, options_for_select(#atendment_assoc.collect { |c| [ c.atendment_region.name, c.id ] }, 1), {:prompt=>"Associado"}, { :class => 'form-control', :required => true, id: 'atendment_atendment_assoc_id' } %>
</div>
<div class="field">
<%= f.select :solution_id, options_for_select(#solutions.collect { |solution| [solution.name, solution.id] }, 0), {:prompt=>"Solução"}, { :class => 'form-control', :required => true, id: 'atendment_solution_id' } %>
</div>
</div>
Route to the new function:
resources :atendments do
collection do
get :update_solution
end
end
AJAX function which calls the "update_solution" and reset solution field's value (app/assets/javascript/atendment.js.coffee):
show_solutions = ->
$.ajax 'update_solution',
type: 'GET'
dataType: 'script'
data: {
atendment_area_id: $("#atendment_atendment_area_id").val()
atendment_region_id: $("#atendment_atendment_region_id").val()
atendment_assoc_id: $("#atendment_atendment_assoc_id").val()
}
error: (jqXHR, textStatus, errorThrown) ->
console.log("AJAX Error: #{textStatus}")
success: (data, textStatus, jqXHR) ->
console.log("OK!")
$(document).ready ->
$('#atendment_atendment_assoc_id').on 'change', ->
show_solutions()
So, I've created a .coffee file to render the partial that will return a new value to the "solution" field "option" tag
(app/views/atendment/update_solution.coffee):
$("#atendment_solution_id").empty()
.append("<%= escape_javascript(render :partial => 'solution') %>")
And, the last but not least, the partial containing the html code for the "option" tag mentioned above (app/views/atendments/_solution.html.erb):
<option value="<%= solution.id %>" selected="selected"><%= solution.nome %></option>
For any reason, the AJAX function doesn't print nothing on console (nor error neither success), but it calls the update_solution.coffee file. The point is, it doesn't update the option value due an error (500 internal server error). I don't know what am I doing wrong. If anybody could help me, I appreciate it.
I would do this with JS, can think any other way.
A function called by onchange that change the display attribute from each field that you need to hide or show.
I solved this with the following code:
assets/js/atendments.js
I changed the code because the last one had many bugs.
function getAssociated(){
var aau_id = $("#atendment_area_user_id").val()
var aru_id = $("#atendment_region_user_id").val();
$.getJSON("/controllers/atendments_controller/getAssociated/"+aru_id,
function ( callback ) {
if (callback != "error"){
var assoc = document.getElementById("atendment_region_associated_id");
while (assoc.firstChild) {
assoc.removeChild(assoc.firstChild);
}
var i = Object.keys(callback).length -1;
$("#atendment_region_associated_id").append("<option value=''>Associated</option>");
while (i >= 0) {
$("#atendment_region_associated_id").append("<option value='"+callback[Object.keys(callback)[i]]+"'>"+Object.keys(callback)[i]+"</option>");
i--;
}
}
});
get_solution_type();
}
function get_solution_type() {
var ara_id = $("#atendment_region_associated_id").val();
$.getJSON("/controllers/atendments_controller/getSolution/"+ara_id,
function ( callback ) {
if (callback != "error"){
var sol = document.getElementById("atendment_solution_id");
while (sol.firstChild) {
sol.removeChild(sol.firstChild);
}
var i = Object.keys(callback).length-1;
while (i >= 0) {
$("#atendment_solution_id").append("<option value='"+callback[Object.keys(callback)[i]]+"'>"+Object.keys(callback)[i]+"</option>");
i--;
}
}
});
var aau_id = $("#atendment_area_user_id").val();
$.getJSON("/controllers/atendments_controller/getType/"+aau_id,
function ( callback ) {
if (callback != "erro"){
var type = document.getElementById("atendment_type_id");
while (type.firstChild) {
type.removeChild(type.firstChild);
}
var i = 0;
while (i < (Object.keys(callback).length)) {
$("#atendment_type_id").append("<option value='"+callback[Object.keys(callback)[i]]+"'>"+Object.keys(callback)[i]+"</option>");
i++;
}
}
});
}
The $.getJSON performs ajax request to the controller that responds with JSON and update the select fields option tags.
controllers/atendments_controller
I just retrieve the data from DB and return as JSON
def getAssociated
aru_id = params[:atendment_region_user_id]
aras = AtendmentRegionAssociated.where("SQL here")
if aras.present?
render :json => aras.to_json
else
render :json => "error".to_json
end
end
def getSolution
ara_id = params[:atendment_region_associated_id]
sol = Solution.where("SQL here")
if sol.present?
render :json => sol.to_json
else
render :json => "error".to_json
end
end
def getType
aau_id = params[:atendment_area_user_id]
type = AtendmentType.where("SQL here")
if type.present?
render :json => type.to_json
else
render :json => "error".to_json
end
end
Update the routes and put the javascript functions in select fields onchange property. Now everything is working fine :D
I am trying to create a form that submits on the collection select option, like when I select a value from the dropdown, it should post, what is posted below is not working,
<%= form_tag edit_zone_management_path, :method => 'get', :id => "bar" do %>
<%= collection_select :dropdown, :id, Server.where(:id => #arr),:id, :server_name, :prompt => true, :selected => #sid %>
<%end%>
Can someone please point out what is missing here?
Addition
There is some coffeescript that is bound to this collection select.
$ ->
$("#dropdown_id").live "change", -> // id of the collection_select
index = this.selectedIndex
uid = window.location.pathname.split("/")
if index == 0
index += 1
response = "{ \"key\": { \"value\" : #{index} } }"
#window.location.replace(uid[0]+ "/" + uid[1] + "/" + uid[2] + "/" + uid[3] + "/" +uid[4])
$.ajax({
type: 'POST',
url: '/configuration/zone_management/updategrid/',
data: response,
contentType: "application/json",
});
It looks like you are missing any handler for your $.ajax call, try adding some:
$.ajax({
type: 'POST'
url: '/configuration/zone_management/updategrid/'
data: response
contentType: "application/json"
success: (response) ->
console.log response
alert "Success fired"
error: (response) ->
console.log response
alert "Error fired"
})
This is just example, so adjust your handlers accordingly!
Good luck!
I have this link_to_function
= link_to_remote 'Populate Info From ID', :url => {:controller => 'something',
:action => 'populate_from_id'},
:with => "'id=' + $('account_id').value + '&field_prefix=purchaser'",
:update => {:failure => 'account_id_error'}
I have converted many of them in a rails upgrade with , :remote => true, :method => :post
But i dont know how to add the with condition to grab the value out...any ideas
All the AJAX-specific options representing callbacks are gone in Rails 3 link_to helpers. You'll have to write your own javascript to handle more complex remote actions like your example.
Here's a quick rewrite:
# Your template
= link_to 'Populate Info From ID', :url => {:controller => 'something',
:action => 'populate_from_id'}, :id => "#populate_info"
# In javascript, assuming jquery and
# an element #account_id with a data-id attribute
$("#populate_info").on("click", function() {
$.ajax({
method: "POST",
data: { id: $('#account_id').data("id"), field_prefix: "purchaser" }
error: account_id_error
});
return false;
});
Useful blog post: http://www.simonecarletti.com/blog/2010/06/unobtrusive-javascript-in-rails-3/
Lots of great documentation here: http://api.jquery.com/jQuery.ajax/
You beat me to it I came up with this
$('.populate_id').click(function(e){
e.preventDefault();
var url = $(this).attr('href');
var failure = $('#' + $(this).attr('failure'));
failure.html('');
var element = $('#' + $(this).attr('element'));
var id = element.val();
var url_extra = 'account_id=' + id + '&field_prefix=purchaser';
$.ajax({
url: url,
data: url_extra,
type: 'post',
error: function (data) {
failure.html(data.responseText);
}
});
return false;
});
I want to add an onclick option to link_to method for loading an modal dialog box...i am using rails version 2.3.8 and i searched on google and could not do it. Plz anybody help me?
My link_to method as follows.
<%= link_to 'All countries',{:controller=>'countries', :action=>'new'}, :remote => true %>
If you are using 2.3.8, you don't have :remote => true. You need to use link_to_remote if you are try to do an ajax action.
So it would look something like:
<%= link_to_remote 'All countries', :url => {:controller => 'countries', :action => 'new'}%>
<div id="populate_me"></div>
and your new method would have to handle the ajax request with something like
countries_controller.rb
def new
<do something>
render :update do |page|
page.replace_html 'populate_me', :partial => 'whatever'
end
end
UPDATED
If you want the onclick in addition to the ajax action, you can just pass it into the html options:
<%= link_to_remote 'All countries', :url => {:controller => 'countries', :action => 'new'}, :html => {:onclick => 'alert("some javascript executed before ajax")'} %>
You can add this to the link:
, :class => "pop light", :id => "modal_link"
Then, your JS shows something ilke this:
<script type="text/javascript">
$(document).ready(function() {
$('a.poplight[href^=#]').click(function() {
var popID = $(this).attr('rel'); //Get Popup Name
var popURL = $(this).attr('href'); //Get Popup href to define size
var query= popURL.split('?');
var dim= query[1].split('&');
var popWidth = dim[0].split('=')[1]; //Gets the first query string value
$('#' + popID).fadeIn().css({ 'width': Number( popWidth ) }).prepend('');
$('a.close').hide();
var popMargTop = ($('#' + popID).height() + 80) / 2;
var popMargLeft = ($('#' + popID).width() + 80) / 2;
$('#' + popID).css({
'margin-top' : -popMargTop,
'margin-left' : -popMargLeft
});
$('body').append('<div id="fade"></div>');
$('#fade').css({'filter' : 'alpha(opacity=80)'}).fadeIn();
return false;
});
$('a.close').live('click', function() {
$('#fade , .popup_block').fadeOut(function() {
$('#fade, a.close').remove();
});
return false;
});
$('#modal_link').click();
});
</script>