2009-02-22 2 views
2

Выпадающее меню (созданное select_tag) в моем приложении должно вызывать действие категории фильтра, как только пользователь изменяет значение в выпадающем меню И нажимает кнопку «Go» ,RJS: Использование watch_field on select_tag

Теперь я хотел бы избавиться от кнопки «Перейти» и иметь наблюдателя (наблюдаемое_поле?), Вызывать действие категории фильтра, как только пользователь изменит значение в раскрывающемся меню.

Ниже вы видите код, который я написал. Он работает с помощью кнопки Go'-Button, но не работает, просто изменив значение в раскрывающемся меню. Что случилось с моим помощником наблюдения_категории?

View-парциальное с выпадающего меню и список проектов

<!-- drop down menu --> 
    <% form_tag(filter_category_path(:id), :method => :post, :class => 'categories') do %> 
     <label>Categories</label> 
     <%= select_tag(:category, options_for_select(Category.all.map {|category| [category.name, category.id]}, @category_id)) %> 
     <!-- i would like to get rid of this button --> 
     <%= submit_tag "Go" %> 
    <% end %> 

    <!-- list of projects related to categories chosen in drop down menu --> 
    <ul class="projects"> 
    <% @projects.each do |_project| %> 
     <li> 
     <%= link_to(_project.name, _project) %> 
     </li> 
    <% end %> 
    </ul> 

    <%= observe_category_select -%> 

HelperMethod

def observe_category_select 
    observe_field(
        :category, 
        :url  => filter_category_path(:id), 
        :with  => 'category', 
        :on   => 'change' 
    ) 
    end 

Javascript-Вывод HelperMethod

<script type="text/javascript"> 
//<![CDATA[ 
    new Form.Element.EventObserver('category', function(element, value) { 
    new Ajax.Request('/categories/id/filter', {asynchronous:true, evalScripts:true, parameters:'category=' + encodeURIComponent(value) + '&authenticity_token=' + encodeURIComponent('edc8b20b701f72285068290779f7ed17cfc1cf8c')}) 
    }, 'change') 
//]]> 
</script> 

Категории контроллер

class CategoriesController < ApplicationController 
    def show 
    @category = Category.find(params[:id]) 
    @category_id = @category.id 
    @projects = @category.projects.find(:all) 

    respond_to do |format| 
     format.html # index.html.erb 
    end 
    end 

    def index 
    @projects = Category.find(params[:id]).projects.find(:all) 

    respond_to do |format| 
     format.html # index.html.erb 
    end 
    end 

    def filter 
    @category = Category.find(params[:category]) 
    @category_id = @category.id 
    @projects = @category.projects.find(:all) 

    respond_to do |format| 
     format.html # index.html.erb 
    end  
    end 

конец

Вывод «рейк маршрутов | Grep фильтр»

   filter_category POST /categories/:id/filter     {:controller=>"categories", :action=>"filter"} 
    formatted_filter_category POST /categories/:id/filter.:format   {:controller=>"categories", :action=>"filter"} 

ответ

6

Действия вашего контроллера фильтра должны отвечать на Javascript вместо обычного HTTP-запроса.

def filter 
    @category = Category.find(params[:category]) 
    @category_id = @category.id 
    @projects = @category.projects.find(:all) 

    respond_to do |format| 
    format.js # filter.rjs 
    end  
end 

Или, если вы хотите, чтобы действия по реагированию в любом контексте, положить как в блоке:

respond_to do |format| 
    format.html # filter.html.erb 
    format.js # filter.rjs 
end  

Это требует от вас, чтобы иметь вид файла filter.rjs, который будет выглядеть примерно так:

page.replace_html :id_of_element_to_replace_html, :partial => "name_of_partial" 
+0

Проблема по-прежнему сохраняется. Согласно Firebug, запрос AJAX отлично подходит: отправляет категорию-значение в .../categories/id/filter – Javier

+0

Я запускал рельсы-отладчик на localhost, и все действие фильтра работает так, как должно. Кажется, что все работает хорошо, но список с проектами ниже выпадающего меню не меняется, как ожидалось. Любой другой намек? – Javier

+0

... хотя @category, @category_id и @projects имеют значения, которые они должны перед ответом. – Javier

1

Моя первая мысль была, может быть некоторые проблемы обзорных. Я предполагаю, что filter_category_path является одним из ваших помощников маршрутного маршрута - идентификатор или значение категории (в: с) могут не быть в области вспомогательного метода.

Когда вы просматриваете страницу, вы можете увидеть JavaScript, который выводится по вызову observ_field?

Используя Firebug, вы можете видеть любые сделанные запросы Ajax?

Что-нибудь появляется в вашем развитии.log?

+0

Да, filter_category_path является одним из моих помощников маршрутного маршрута: я просто добавил более подробное описание моего кода, проверьте его (не так много символов, оставшихся в окне комментариев. :-)). – Javier

+0

Если я запустил его на своем локальном хосте, это то, что я вижу на серверной консоли: Обработка категорийController # filter (для 127.0.0.1 в 2009-02-22 23:29:29) [POST] Параметры: { «category» => «3», «authenticity_token» => «edc8b20b701f72285068290779f7ed17cfc1cf8c», «id» => «id»} ... и т. д. – Javier

+0

... но проекты в списке ниже выпадающего меню не меняются! – Javier

0

У меня была такая же проблема в моем фактическом проекте.Я решил ее с OnChange атрибутом в выберите тег:

<%= select_tag @procuct, 
     options_for_select(
      @product.properties.map {|property| [property.name, property.id]}), 
     :onchange => "HERE_A_CALL_TO_YOUR_JS_FUNCTION();" %> 

UPDATE: Я поставил Ajax вызова в функции JS, вместо этого вы можете поместить все в OnChange заявление, я думаю, вы также можете поместить «родные Rails «Методы JS там.

+0

Спасибо, но это просто переопределяет RJS и использует простой Javascript. Не то, что я ищу. – Javier

+0

Я согласен, что метод Яна Террелла намного шире. Я тоже приспособию его метод. –

1
def observe_category_select 
    observe_field(
        :category, 
        :url  => filter_category_path(:id), 
        :with  => :category_id, 
        :on   => :onchange, 
        :update  => :projects 
    ) 
    end 

The: onchange is gotcha - мне понадобилось много времени, чтобы разобраться. EDIT: Похоже, вы сработали.

Если вы хотите сбросить состояние выпадающего и проект отображения включает в себя функцию, как это в тонированном парциальном:

<%= link_to_function "close category", :title => 'close category' do |page| 
     page.select("#category").each do |element| 
      element.value = "Choose Category" 
      page << "window.fireEvent($(\"category\"), 'change');" 
     end 
     page.replace_html :projects, "<li></li>" 
    end-%> 

Это установит список выбора значения по умолчанию и удалить все элементы списка связанных до последней отображаемой категории и получить команду ul, чтобы новые ли отображались по умолчанию. FireEvent должен быть вызван или наблюдатель не будет работать, если вы выберете ту же категорию, которая была просто скрыта.

Поскольку наблюдатель увольняют действие контроллер должен иметь дело с этим:

def filter 
    begin   
    @category = Category.find(params[:category]) 
    @category_id = @category.id 
    @projects = @category.projects.find(:all) 
    rescue 
    @category = "choose" 
    end 
    render :layout => false 
end 

Если ни одна категория не найден набор @category в строку и испытания в целях частичного

<% if @category.eql?('choose') %> 
    <li>choose category</li> 
<% else %> 
# loop through projects returning them wrapped in li tags 
<% end %> 

Не очень, но это работает.

0

FWIW - Я по-прежнему новичок в рельсах, и я наткнулся на то, что новое настраиваемое действие необходимо определить в файле routes.rb (что очевидно, оглядываясь назад, но мне никогда не приходилось это делать раньше).

Если вы используете спокойные маршруты, просто примените: collection => {: filter =>: get} до конца вашей линии маршрута ресурсов (например, map.resource: categories,: collection => {: filter =>: get}).

Надеюсь, что кто-то поможет.

Смежные вопросы