0

Awesome Nested Set gemを使用して階層を作成しています。この階層を表示します。Rails:dbから起動時にアコーディオンを動的に読み込む方法

私は部分的

を呼び出しています典型的なコントローラのアクション私のindexアクションで

klasses_controller.rb

def index 
    @klasses = Klass.where(depth: 0).order('lft ASC') 
end 

klasses/index.rb

<div id="accordion" role="tablist" aria-multiselectable="true"> 
    <% @klasses.each do |klass| %> 
     <%= render :partial => "klass", locals: {klass: klass} %> 
    <% end %> 
</div> 

とインデックスページを持っています

klasses/_klass.html.erb

<div class="klass"> 
    <div class="klass-header" role="tab" id="heading-<%=klass.id%>"> 
     <h5 class="mb-0"> 
     <a data-toggle="collapse" 
      data-parent="#accordion" 
      href="#collapse-<%=klass.id%>" 
      aria-expanded="false" 
      aria-controls="collapse-<%=klass.id%>"> 

      <%= klass.symbol + " : " + klass.title%> 
     </a> 
     </h5> 
    </div> 

    <div id="collapse-<%=klass.id%>" 
     class="collapse" 
     role="tabpanel" 
     aria-labelledby="heading-<%=klass.id%>"> 

     <div class="klass-block"> 
     <Here is where I want to render partial for each child> 
     </div> 
    </div> 
</div> 

これは標準のアコーディオンであり、そのまま動作します。ここに私は非常に大きなデータベースを持っていると私は不必要に何かをレンダリングしたくない問題です。ヘッダがクリックされるまで待ってから、非同期的にクラスiの子を取得し、同じ部分を使ってそれぞれをクリックしてレンダリングします。

どうすればこの問題を解決できますか?ルート/コントローラアクションの組み合わせを使用する方法はありますか?または、coffee/java-scriptの記述を開始する必要がありますか?私は誰もが歓迎される例を知っているので、ホイールを再発明しようとしていません。

+0

'<それぞれの子に部分的にレンダリングしたい場所はあります> '領域で、各子を展開するリンクはどうでしょうか?リンクは子を示すajaxリクエストで、同じ部分的な '_klass.html.erb'をレンダリングし、リンクを部分的に置き換えます。新しくレンダリングされた子は、もちろんそれ自身の子を拡張するためのajaxリンクを持っています。 –

+0

もし私がそれをしたら、少なくともリンクのそれぞれの子供の名前をロードしたいと思うでしょう。その場合、最初のインデックスアクションでルートノードの子ノードをロードする必要がありますか?ヘッダーのリンクをダブルデューティーで子供に呼びかけ、折り畳みパネルを開くことができますか? – mkrinblk

+0

はい、最初のインデックスアクションで、ルートノードの子ノード名(およびリンクのパスのIDも)をロードできます。もう1つの選択肢は、すべての子どもの名前を取得したくない場合は、一般的な「子を展開」リンクまたはボタンを使用することです。はい、新しいデータを挿入するAJAXレスポンスの一部と同時にアコーディオンを拡張することもできます。 –

答えて

0

多くの可動部分があったため、これは難しい問題でした。それは本物のヘッドチェッカーだったが、後ろから見ればそれはまっすぐである。

まず、カスタムコントローラアクションを使用したいので、ajax呼び出しを受け取るように設定された「子」メソッドのルートを追加しました。

routes.rbを

get 'klasses/:id/children', to: 'klasses#children', as: 'children_of' 

klasses_controller.rb

def index 
    @klasses = Klass.where(depth: 0).order('lft ASC') 
end 

def children 
    respond_to do |format| 
     format.js {render 'children', :klass => @klass } 
    end 
end 

この応答ブロックは、のために呼び出すことがchildren.js.erbを持つことが期待されます。

children.js.erb

$("#collapse-<%[email protected]%>").html("<%= escape_javascript(render :partial => 'klasses/children', locals: { :klass => @klass })%>"); 

これは、我々はに新しいコンテンツを挿入しようとしていると私たちは別の部分を呼び出すのdivを指定する場所です。これは、両方のトリガーのブートストラップのアコーディオンのJSとは、私たちの新しいコントローラのアクションを呼び出します見出しのリンクを持っているので、

<div class="child-block"> 
    <% children = @klass.children %> 
    <% children.each do |child| %> 
     <%= render :partial => 'klasses/klass', locals: { :klass => child } %> 
    <% end %> 
</div> 

_children.html.erbは、最後に私は私の_klass.html.erbは部分書き直しました。かなりそれだ

_klass.html.erb

<div class="klass"> 
    <div class="klass-header" role="tab" id="heading-<%=klass.id%>"> 
     <h5 class="mb-0"> 

    <%= link_to klass.symbol + " : " + klass.title, 
       children_of_path(klass.id), 
       remote: true, 
       :data => { :toggle => "collapse", 
          :parent => "#accordion", 
          :target => "#collapse-#{klass.id}" 

       }, 
       :aria => { :expanded => "false", 
          :controls => "collapse-#{klass.id}" 
       }%> 
     </h5> 
    </div> 

    <div id="collapse-<%=klass.id%>" 
     class="collapse" 
     role="tabpanel" 
     aria-labelledby="heading-<%=klass.id%>"> 

    </div> 
</div> 

。いくつかのパディングを子ブロックに追加すると、コンテンツを動的に読み込むインデントされた階層構造になります。誰もがそれは私に知らせて回避する方法を知っている場合

私は私のコントローラ

protect_from_forgery :except => :children 

で私のカスタムアクションのために、クロスサイトリクエストフォージェリを無効にする必要がありました。

関連する問題