2

私のアプリケーションのドロップダウンメニュー(select_tagによって作成された)は、ユーザーがドロップダウンメニューの値を変更して[実行]ボタンを押すとすぐに、filter-category-actionを呼び出す必要があります。

ここで、[実行]ボタンを削除し、ユーザーがドロップダウンメニューの値を変更するとすぐに、オブザーバー(observe_field?)にfilter-category-actionを呼び出させたいと思います。

以下に私が書いたコードを示します。「実行」ボタンを使用して機能しますが、ドロップダウンメニューの値を変更するだけでは機能しません。私のobserve_category_select-helperの何が問題になっていますか?

表示-ドロップダウンメニューとプロジェクトリストを含む部分

    <!-- 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"}
4

5 に答える 5

6

フィルタコントローラのアクションは、通常のHTTPリクエストだけでなく、Javascriptに応答する必要があります。

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"
于 2009-02-22T23:31:26.230 に答える
1

私の最初の考えは、それがいくつかのスコープの問題かもしれないということでした。filter_category_pathはルートパスヘルパーの1つであると想定しています。つまり、idまたはcategory値(:with内)がヘルパーメソッドのスコープに含まれていない可能性があります。

ページを表示すると、 observe_fieldの呼び出しによって出力されるJavaScriptを確認できますか?

Firebugを使用して、Ajaxリクエストが行われていることを確認できますか?

development.logに何か表示されますか?

于 2009-02-22T21:45:43.130 に答える
1
  def observe_category_select
    observe_field(
                  :category,
                  :url        =>  filter_category_path(:id),
                  :with       =>  :category_id,
                  :on         =>  :onchange,
                  :update     =>  :projects
    )
  end

:onchange が落とし穴です。整理するのに長い時間がかかりました。編集:あなたはそれを解決したようです。

ドロップダウンとプロジェクトの表示状態をリセットする場合は、レンダリングされたパーシャルに次のような関数を含めます。

<%= 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-%>

これにより、選択リストがデフォルト値に設定され、最後に表示されたカテゴリに関連するすべてのリスト項目が削除され、デフォルトから新しい li が表示されるように 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 %>

きれいではありませんが、機能します。

于 2009-03-10T22:27:01.090 に答える
0

FWIW-私はまだrailsにかなり慣れていないので、routes.rbファイルで新しいカスタムアクションを定義する必要があるという事実に遭遇しました(後から考えると明らかですが、これまでこれを行う必要はありませんでした)。

安らかなルートを使用している場合は、:collection => {:filter =>:get}をリソースルート行の最後に追加します(例:map.resource:categories、:collection => {:filter =>:得る})。

それが誰かを助けてくれることを願っています。

于 2010-01-06T22:32:34.657 に答える
0

実際のプロジェクトでも同じ問題がありました。selectタグのonchange属性で解決しました:

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

更新: Ajax 呼び出しを JS 関数に入れました。代わりに、すべてを onchange ステートメントに入れることができます。「ネイティブ Rails」JS メソッドをそこに入れることもできると思います。

于 2009-02-23T09:19:22.230 に答える