Rails. Render a partial within another partial with tabs

0

In my show.html.erb I have a nav-pills . Each of those " pills " have a tab-panel. Well, within these tabs panel I put text and, until now, I had not tried to render a partial one.

The functionality of pills is made with ajax or escape javascript , but the different tabs no, and when I want to render any partial, it does not change me tab , as you can see the next image:

The code is as follows:

_tab_leaderboard.html.erb

<div id="#leaderboard">
  <ul class="nav nav-tabs">
     <li class="active"><a href="#tab_1" data-toggle="tab"><b>Public LeaderBoard</b></a></li>
     <li><a href="#tab_2" data-toggle="tab"><b>Group Leaderboard</b></a></li>
  </ul>
  <div class="tab-content">
     <div class="tab-pane active" id="tab_1">
       <div class="container">
         <div class="col-xs-7">
           <%= render 'competitions/formleaderboard' %>
         </div>
       </div>
     </div>
     <div class="tab-pane" id="tab_2">
       <div class="container">
         <div class="col-xs-11">
           <%= render 'competitions/formGroupLeaderboard' %>
         </div>
       </div>
     </div>
   </div>
 </div>

Basically, I load the two renderings in the two tabs , both in public and in group .

What I wanted to know is how to render the partial according to the tab that is used, since I do not know if in a partial you can use escape javascript as if it were a normal view with your method in the controller .

Update

I've noticed that I only load the tabs well in the pill that loads as active the code in show.html.erb (ie overview ). Here the code where they are loaded:

<ul class="nav nav-pills" id="competitionContentMenu">
  <li id="overview" role="presentation" class="active">
    <%= link_to "Overview", "#overview", :remote => true, html_options = "data-toggle" => "pill" %>
  </li>
  <li id="data" role="presentation">
    <%= link_to "Data", "#data", :remote => true, html_options = "data-toggle" => "pill" %>
  </li>
  <li id="discussion" role="presentation">
    <%= link_to "Discussion", "#discussion", :remote => true, html_options = "data-toggle" => "pill" %>
  </li>
  <li id="leaderboard" role="presentation">
    <%= link_to "Leaderboard", "#leaderboard", :remote => true, html_options = "data-toggle" => "pill" %>
  </li>
  <li id="more" role="presentation">
    <%= link_to "More", "#more", :remote => true, html_options = "data-toggle" => "pill" %>
  </li>
</ul>
<div class="nav-tabs-custom" id="detailed_competition">
  <%= render '/competitions/tab_overview' %>
</div>

The change I do with the following Javascript code ( show.js.erb )

if($("#competitionContentMenu li:first-child").hasClass("active")){
  $('#detailed_competition').html("<%= escape_javascript(render(:partial => '/competitions/tab_overview')) %>")
}
if($("#competitionContentMenu li:nth-child(2)").hasClass("active")){
  $('#detailed_competition').html("<%= escape_javascript(render(:partial => '/competitions/tab_data')) %>")
}
if($("#competitionContentMenu li:nth-child(3)").hasClass("active")){
  $('#detailed_competition').html("<%= escape_javascript(render(:partial => '/competitions/tab_discussion')) %>")
}
if($("#competitionContentMenu li:nth-child(4)").hasClass("active")){
  $('#detailed_competition').html("<%= escape_javascript(render(:partial => '/competitions/tab_leaderboard')) %>")
}
if($("#competitionContentMenu li:nth-child(5)").hasClass("active")){
  $('#detailed_competition').html("<%= escape_javascript(render(:partial => '/competitions/tab_more')) %>")
}

In short: Only when I'm in Overview are the tabs changed correctly. In the others, the same thing happens to me as in what was previously mentioned in Leaderboard (either doing render , or <p></p> ). Neither the console of the rails server nor the browser shows me any errors.

    
asked by Jorge Vela Plaza 29.07.2017 в 00:45
source

1 answer

1

Verify that you have the div with id="detailed_competition" in this way:

<div id="detailed_competition"><%= render(partial: 'competitions/tab_overview') %></div>

This will initially load the partial _tab_overview.html.erb and then the content of the div will be replaced with the corresponding partial according to the logic of show.js.erb .

That's the only necessary change I had to make to your code to make it work; the view was like this:

<ul class="nav nav-pills" id="competitionContentMenu">
  <li id="overview" role="presentation" class="active">
    <%= link_to "Overview", "#overview", :remote => true, html_options = "data-toggle" => "pill" %>
  </li>
  <li id="data" role="presentation">
    <%= link_to "Data", "#data", :remote => true, html_options = "data-toggle" => "pill" %>
  </li>
  <li id="discussion" role="presentation">
    <%= link_to "Discussion", "#discussion", :remote => true, html_options = "data-toggle" => "pill" %>
  </li>
  <li id="leaderboard" role="presentation">
    <%= link_to "Leaderboard", "#leaderboard", :remote => true, html_options = "data-toggle" => "pill" %>
  </li>
  <li id="more" role="presentation">
    <%= link_to "More", "#more", :remote => true, html_options = "data-toggle" => "pill" %>
  </li>
</ul>
<div id="detailed_competition"><%= render(partial: 'competitions/tab_overview') %></div>

As an additional note, you could optimize your code by removing the logic of show.js.erb , since this causes * all ** partials to be generated (even if they are not displayed) each time you change the menu (you can verify it if you look at the code generated in your browser). The optimum (and why you use ajax ) is that only the code of the menu (i.e. pill ) to which you click is generated.

You can do this by passing a variable to the action show that indicates what is the partial that it should generate; for example:

show.html.erb

<ul class="nav nav-pills" id="competitionContentMenu">
  <li id="overview" role="presentation" class="active">
    <%= link_to "Overview", "?tab=overview#", :remote => true, html_options = "data-toggle" => "pill" %>
  </li>
  <li id="data" role="presentation">
    <%= link_to "Data", "?tab=data#", :remote => true, html_options = "data-toggle" => "pill" %>
  </li>
  <li id="discussion" role="presentation">
    <%= link_to "Discussion", "?tab=discussion#", :remote => true, html_options = "data-toggle" => "pill" %>
  </li>
  <li id="leaderboard" role="presentation">
    <%= link_to "Leaderboard", "?tab=leaderboard#", :remote => true, html_options = "data-toggle" => "pill" %>
  </li>
  <li id="more" role="presentation">
    <%= link_to "More", "?tab=more#", :remote => true, html_options = "data-toggle" => "pill" %>
  </li>
</ul>
<div id="detailed_competition"><%= render(partial: 'competitions/tab_overview') %></div>

driver.rb

def show
  @partial = "competitions/tab_#{params[:tab]}"

  respond_to do |format|
    format.html {}
    format.js {}
  end
end

show.js.erb

$('#detailed_competition').html("<%= j(render(partial: @partial)) %>")

Now, every time you click on an element (i.e. pill ) the following will happen:

  • The tab parameter is sent with the name of the partial that you want to show.
  • In the controller you receive the value of the parameter, you add competitions/tab_ and save it in the variable @partial .
  • In the js view, you only replace the previous content of the%% main% (ie div ) with the new one, using the variable detailed_competition to dynamically select the appropriate template .
  • In this way you can generate only the necessary code, thus optimizing the load of each tab .

        
    answered by 31.07.2017 в 18:03