I have an issue with my loop on a Bootstrap tab.
%ul.nav.nav-pills.nav-fill{role: "tablist"}
- #matrices.each_with_index do |matrice, i|
%li.nav-item
= link_to "#matrice_#{matrice.id}", class:"nav-link #{"active show" if i.zero?}", "data-toggle" => "tab" do
= matrice.name
.tab-content
- #matrices.each_with_index do |matrice, i|
%div{id:"matrice_#{matrice.id}", class:"tab-pane #{"active show" if i.zero?}", role: "tabpanel"}
= matrice.name
First tab is display well with the content but when I click on the second tab, first tab content is also display. I want to hide the previous tab content at click.
How to fix it? Can I make one loop over two HTML div?
Haml strictly follows indentation. Seems the loop in the second tab is put under same line where first tab is.
Try the below way.
%ul.nav.nav-tabs
%li.active
%a{"data-toggle": "tab", href: "#tab_menu1"}
Graphical View
%li
%a{"data-toggle": "tab", href: "#tab_menu2"}
Tabular View
%div.tab-content
%div.tab-pane.in.active{id: "tab_menu1"}
= render partial: "menu1_view"
%div.tab-pane{id: "tab_menu2"}
= render partial: "menu2_view"
You can refer https://www.w3schools.com/bootstrap/bootstrap_tabs_pills.asp for more details.
Add your loops under the %div.tab-page tag.
Hope this helps!!
Related
In my Rails 7 app I've got CustomersController where inside there is show action with the corresponding show.slim view. Inside this view I want to have 2 tabs:
"Data", with text of "This is data page" - this tab should be active after user hits show.slim
"Customer Users", with text of "Here is the list of Customer Users".
When user hits show url (customer_path) he should be able to see Data tab as active and after click "Customer Users" he/she should not be redirected anyway but stays at the page and the text of "Here is the list of Customer Users" should be rendered. I want to use turbo-frame to control tabs switching, no extra JS needed. I'm using tailwindcss.
So what I did is that:
customers/show.slim:
div.tabs
button.tab-button[data-turbo-frame="customer_data" data-turbo-frame-target="data"] Data
button.tab-button[data-turbo-frame="customer_users" data-turbo-frame-target="users"] Customer Users
= turbo_frame_tag "data" do
h1 Data
p This is data page
= turbo_frame_tag "users" do
h1 Customer Users
p Here is the list of Customer Users
With some extra css:
.tab-button {
#apply inline-block py-2 px-4 border-b-2 font-medium text-sm focus:outline-none transition duration-150 ease-in-out;
}
.tab-button.active {
#apply border-indigo-500 text-gray-900;
}
.tab-button:hover:not(.active) {
#apply border-indigo-500 text-gray-900;
}
.tabs {
#apply border-b border-gray-200 px-4 flex justify-start;
}
Instead I'm getting this view:
Like I said, at the first glance I want to understand what should be done to make it work? It has to be turbo-frame because EOD I'll have few view components for that.
Turbo works by making requests to the back-end, so if you wish to render tab contents in the same request, you would have to use javascript for the hiding & showing of the tabs.
If you do wish to use turbo, then you would have to change the way you approach this:
Since only one tab can be open at once, you don't need two turbo frames. You should have only one.
customers/show.slim
div.tabs
button.tab-button[data-turbo-frame="tab_content"] Data
button.tab-button[data-turbo-frame="tab_content"] Customer Users
= turbo_frame_tag "tab_content"
Create a controller action for each of the tabs
app/controllers/customer_tabs_controller.rb
class CustomerTabsController < ApplicationController
def data
end
def customer_users
end
end
routes.rb
Rails.application.routes.draw do
# ...
resource :customer_tab, only: [] do
get :data
get :customer_users
end
end
Add view templates for these actions, with a turbo_frame containing the tab content. When rendered, the previous contents of the frame will be replaced by contents here.
app/views/customer_tabs/data.html.erb
= turbo_frame_tag "tab_content" do
h1 Data
p This is data page
app/views/customer_tabs/customer_users.html.erb
= turbo_frame_tag "tab_content" do
h1 Customer Users
p Here is the list of Customer Users
Then, you have to add the links to tab buttons so clicking them will render the appropriate content.
customers/show.slim
div.tabs
/ To avoid having to specify `method: :get`, `link_to` could be used
= button_to "Data", data_customer_tab_path, class: "tab-button", method: :get, data: { turbo_frame: "tab_content" }
= button_to "Customer Users", customer_users_customer_tab_path, class: "tab-button", method: :get, data: { turbo_frame: "tab_content" }
= turbo_frame_tag "tab_content"
Now, clicking the tabs will open the respective tab content. To have the first tab load automatically upon opening the page, you would have to use eager loading frames
customers/show.slim
div.tabs
= button_to "Data", data_customer_tab_path, class: "tab-button", method: :get, data: { turbo_frame: "tab_content" }
= button_to "Customer Users", customer_users_customer_tab_path, class: "tab-button", method: :get, data: { turbo_frame: "tab_content" }
/ Will make a request for the data tab immediately and display it.
= turbo_frame_tag "tab_content", src: data_customer_tab_path do
/ The content that will be shown before the request to `data_customer_tab_path` completes
p Loading...
As
I'm using the bootstrap tab-pane inside of my rails application. Inside of each tab I want to use the Masonry GEM. However, all the items are stacking on top of eachother.
.container
%ul.nav.nav-tabs
- if #project.user == current_user
%li
%a{href: new_project_room_path(#project)} <i class='fa fa-plus-circle'></i> Add Room
- #rooms.each do |room|
%li
%a{"data-toggle" => "tab", href: "##{dom_id(room)}"}= room.title
.tab-content
- #rooms.each do |room|
.tab-pane{id: dom_id(room)}
.container-fluid.page.page-block
.masonry-container.centered.transitions-enabled.infinite-scroll.clearfix
- room.products.each do |product|
.box.col3
= product.title
If I resize the page, they display side by side, the way I want them to. How can I get it to display like this all the time?
Also as an FYI, when I use similar code not inside of a tab-pane, everything works fine.
.container-fluid.page.page-block
.masonry-container.centered.transitions-enabled.infinite-scroll.clearfix
- if current_user.is_designer?
= link_to new_project_path do
.box.col3.create_projects_well#add_project
%span.text-center#create_project
%i.fa.fa-plus-circle.fa-3x
%br
Add a project
- #projects.each do |project|
.box.col3
- if project.image_url != nil
= link_to(image_tag(project.image_url, class: "img-responsive opaq"), user_project_path(project.user, project))
- else
= link_to(image_tag("150.png", class: "img-responsive opaq"), user_project_path(project.user, project))
Try removing fluid.
.container.page.page-block
.masonry-container.centered.transitions-enabled.infinite-scroll.clearfix
- if current_user.is_designer?
= link_to new_project_path do
.box.col3.create_projects_well#add_project
%span.text-center#create_project
%i.fa.fa-plus-circle.fa-3x
%br
Add a project
According to the bootstrap fluid grid documentation, "Nesting with fluid grids is a bit different: the number of nested columns doesn't need to match the parent. Instead, your columns are reset at each level because each row takes up 100% of the parent column."
Not sure if I understand correctly. But if you want to have the masonry to always be the same width you may want to checkout the isFitWidth Property
link to masonry doc
http://masonry.desandro.com/options.html#isfitwidth
"isFitWidth": true
/* center container with CSS */
#fit-width .masonry {
margin: 0 auto;
}
codepen demo
http://codepen.io/desandro/pen/nGLvx
Ruby on Rails 3. I have a page with several div blocks. I am trying to seperate them into two pages. I want a button at the bottom of the page which will change the rendered partial.
The "render 'news'" is the first partial loaded. I want the "Archived News Postings" button to change the 'news' to 'archive_news'
<%= render 'news' %>
<%= link_to render(:partial => 'archive_news'), :class => 'btn' %> <button type="button" class="archive">Archived News Postings</button>
Can I get a pointer? Thank you
It depends on what you want to achieve really. For instance, these two options could be considered:
1) You could fetch both the news items and the archived ones. Then render two divs with the corresponding news items. The one with news is shown while the other has display: none; in the CSS. This allows you to use JavaScript to toggle the divs visibility. This obviously has some disadvantages with amount of data etc. but it gives an idea what to think about.
Something along these lines:
controller:
def some_action
#items = ...
#archived_items = ...
end
view:
<div id="news">
<% #items.each do |i|
...
</div>
<div id="archived_news">
<% #archived_items.each do |i|
...
</div>
css:
#archived_news {
display: none;
}
2) Another way would be to rely on asynchronously fetching the news items as the used wants to "toggle". This can be done with AJAX. This allows for more flexibility if the data set is large. You can even have "fetch more" in some way that archived news items are loaded on demand if needed.
If you shed some light what you might need it is possible to give a more specific answer.
I have seen similar questions answered but I cannot find exactly my problem and I can't work out how to change the others to make them fit.
I am writing a simple rails 3 app that has 2 main sections. One called Students and one called iConnects with multiple pages for each. I have a simple navigation bar to allow navigation to either by navigating to the first record of either of these sections when clicked. This click also sets a class which has a colour set on it in CSS to indicate which section you are on. This however only works if you click that link once. If you navigate to any of the sub-pages e.g. students/2 the class is obviously not present there and there is no visual indication.
My question is how do I have a persistent class added to the navigation to indicate whether the user is on either students or iConnects?
I have a separate partial in my shared which I am pulling in with this code..
<div id="section_navigation">
<%= link_to 'iConnect', #iconnects.first, :class => current_page?(#iconnects.first) ? "current" : "" %>
<%= link_to 'Students', #pages.first, :class => current_page?(#pages.first) ? "current" : "" %>
</div>
And from my students show.html.erb
<%= render :partial => 'shared/navigation' %>
I am fairly new to rails and so can't think how to do this myself and I am resisting the urge to do it in a Javascript way as I know backend output is the correct approach for this.
Any hints or tips are more than welcome. Thank you for your time...
Use something like simple-navigation
I'm new to Rails and web development in general. I'm trying to better understand what are the options to render different buttons on my views depending on which user is visiting a page. I'm working with Rails 3.2.
2 specific cases for me:
On my movie page, I want to display a Bookmark button. The button should say "add bookmark" and not be checked if the user is not logged in or if the movie is not in user's bookmark list. The button should say "remove bookmark" and be checked (with an "active" css class) if the user added the movie in her bookmarks.
If user search for "action movie", the view renders a list of movies. Each item of the list should display an "add bookmark" / "remove bookmark" button depending on whether the movie is in the user's bookmark list.
What are best practices to manage my buttons text, actions, and display depending on my user status? Where does the code go (view, javascript...), and what key methods I would need to implement?
Well, best practice is to using something like Draper: https://github.com/jcasimir/draper which handles the responsibility of presenting the correct content based on a set of conditions.
This would work however, but should probalby be refactored into a Draper Decorator:
<% if user.has_bookmarked(#movie) %>
<%= link_to 'Remove bookmark', remove_bookmark_path%>
<% else %>
<%= link_to 'Add bookmark', add_boookmark_path %>
but again, in the decorator you could just do it once
def display_correct_bookmark_link_for_movie(movie)
if current_user.has_bookmarked(movie)
h.link_to 'Remove bookmark', remove_bookmark_path
else
h.link_to 'Add bookmark', add_boookmark_path
end
end
and then in your view you could just call:
<%= display_correct_bookmark_link_for_movie(#movie) %>
Otherwise, you'll be repeating that logic all over your views which is not good.
Obviously some of that is psuedo-code but I think you get my drift.