Как сделать вызовы Ajax с Rails 3 с помощью remote_function?
Я пытаюсь сделать вызов onchange в поле select. Для моего приложения я использую jquery.js и rails.js, как упоминалось, чтобы использовать UJS. Но все же код, который сгенерирован, предназначен для Prototype, а не для jQuery ajax-вызовов. Мой код выглядит следующим образом:
<%= select_tag :category,
options_for_select(
Category.find(:all,:select=>"name,id").collect{|c| [c.name,c.id]}),
:onchange => remote_function(:url => {:controller => "posts",
:action => "filter_post",
:filter =>"category"},
:with=>"'category_id=' + $('#category').val()") %>
Код, сгенерированный этим:
new Ajax.Request('/posts/filter_posts?filter=category', {asynchronous:true, evalScripts:true,
parameters:'category_id=' + $('#category').val() + '&authenticity_token=' +
encodeURIComponent('CCyYj1wqXtddK6pUV6bAxw0CqZ4lbBxDGQHp13Y/jMY=')})
Ответы
Ответ 1
Как сказал Сергей: в рельсах нет удаленной_функции.
Решение состоит в том, чтобы ненавязчиво добавить обработчик onchange, используя что-то вроде:
$(function($) {
$("#selector_for_element").change(function() {
$.ajax({url: '<%= url_for :action => 'action_name', :id => @model.id %>',
data: 'selected=' + this.value,
dataType: 'script'})
});
});
Это вызовет метод action_name
в текущем контроллере, передав результат selected=...
в качестве параметра. Теперь вы можете вернуть часть javascript, например, используя что-то вроде:
calculated = calculate_some_value_using(params[:selected])
render(:update) {|page|
page << "$('#selector_for_field_to_update).html(#{calculated})"
}
в контроллере. Строка, добавленная к странице '' ', должна быть действительной javascript и будет выполнена автоматически, если вы используете $.ajax.
EDIT: FYI, мы недавно добавили помощник выбора в jquery-ujs, поэтому вы можете сделать этот ненавязчивый способ с помощью встроенного адаптера jquery-ujs:
<%= select_tag :category_id,
options_for_select(
Category.find(:all,:select=>"name,id").collect{|c| [c.name,c.id]}),
:data => { :remote => true, :url => url_for(:controller => "posts",
:action => "filter_post",
:filter =>"category") } %>
Если честно, добавление события выбора изменений действительно никогда не будет "ненавязчивым", поскольку для пользователей с отключенным javascript нет изящного отказа, если ваша форма не зависит от результата запроса AJAX.
Ответ 2
В рельсах нет remote_function 3. Если вы используете jQuery, вы можете сделать что-то вроде этого:
$.ajax({
type: 'POST',
url: 'http://your_url/blah',
data: 'param1=value1¶ms2=value2',
success: function(data){eval(data);}
});
Ответ 3
Ниже приведен простой фрагмент jQuery из моего представления haml
:javascript
$("#select_box_id").change(function() {
$.post('#{target_url}?param_one='+$(this).val());
});
Надеюсь, это поможет.
Спасибо..
Ответ 4
Если у вас возникла проблема с тем, что я обновил большое приложение rails для rails 3, которое сильно использовало remote_function, вы можете добиться ограниченной обратной совместимости, добавив метод application_helper, который генерирует код jQuery в формате, предложенном другими ответами здесь, Я смог использовать этот код так, как есть, хотя должен был обновить один кусок кода вызова, чтобы использовать параметр new: success script, а не хеш-вариант: update hash, который здесь не поддерживается. Это может выкупить некоторое время, чтобы в конечном итоге реорганизовать все вызовы remote_function для использования ненавязчивых обратных вызовов событий jquery-ujs:
def remote_function(options)
("$.ajax({url: '#{ url_for(options[:url]) }', type: '#{ options[:method] || 'GET' }', " +
"data: #{ options[:with] ? options[:with] + '&' : '' } + " +
"'authenticity_token=' + encodeURIComponent('#{ form_authenticity_token }')" +
(options[:data_type] ? ", dataType: '" + options[:data_type] + "'" : "") +
(options[:success] ? ", success: function(response) {" + options[:success] + "}" : "") +
(options[:before] ? ", beforeSend: function(data) {" + options[:before] + "}" : "") + "});").html_safe
end
Ответ 5
Ajax Вызов для контроллеров-действия с параметрами:
function combined_search() {
var countries = $('#countries').val();
var albums = $('#albums').val();
var artists = $('#artists').val();
$.ajax({
url:"<%=url_for :controller => 'music_on_demand',:action => 'combined_search' %>",
data:'country=' + encodeURIComponent(countries) + '&albums=' + encodeURIComponent(albums) + '&artists=' + encodeURIComponent(artists),
cache:false,
success:function (data) {
}
})
}