How to render HTML hierarchy correctly - ruby-on-rails

I need to deal with the front-end of my application only. I understand how to write the templates but, for some reason, a few specific elements jump out of the hierarchy I've created:
%html
%head
%meta{ content: 'text/html; charset=UTF-8', 'http-equiv': 'Content-Type' }
%title Title
%body{ data: { action: action_name, controller: controller_name.camelcase } }
.page-container
= render 'application/timeout'
%header
= render 'application/cookie_banner'
.container
.row
.logo.col-3
= link_to root_path do
= image_tag 'logo.jpg'
.login.col-9
= render 'application/user_information'
%nav.navbar.navbar-expand.navbar-light
= render 'navigation/by_role'
.content-container.container
.row
%section
.section-container
= render 'application/notifications'
= render 'application/flash'
= yield
= render 'application/footer'
I want to wrap the page in '.page-container', but the footer and content-container.container elements are outside the wrapper:
I need the rendering to follow my element hierarchy.

Related

After adding the header getting the blank pdf page in wicked_pdf Rails

My code working perfect without header, but after adding header I am getting the blank pdf page. Please solve my issue
def show
#resume = current_user.resume
respond_to do |format|
format.html{ }
format.pdf do
render template: 'student/resumes/show',
pdf: "#{current_user.first_name}.pdf",
# :header => { :content => render_to_string({:template => 'student/resumes/header.pdf.erb'})}
header: {
html: {
template: 'student/resumes/header'},
layout: 'pdf.erb',
handlers: [:erb],
formats: [:pdf]
}
end
end
end
Same issue i also faced with the code so I tried with lots of combinations but at the last i found the following solutions which worked for me
Followed the proper HTML DOM format which works perfectly:
<!DOCTYPE html>
<html>
<head>
<title></title>
<link href=“https://fonts.googleapis.com/css?family=Roboto:400,700” rel=“stylesheet”>
<%= wicked_pdf_stylesheet_link_tag ‘pdf’ %>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
Above is Example for Header
Also I added the following property in the controller to generate PDF
render template: 'backend/report_result/report',
pdf: "test",
header: { html: { template: 'backend/report_result/header'}},
margin: { top: 30, bottom: 20, left: 25, right: 25 }
Make sure to use all properties proper along with the view with pdf.erb format
Your closing brackets are in the wrong place. header - html should contain all those other keys
def show
#resume = current_user.resume
respond_to do |format|
format.html{ }
format.pdf do
render template: 'student/resumes/show',
pdf: "#{current_user.first_name}.pdf",
# :header => { :content => render_to_string({:template => 'student/resumes/header.pdf.erb'})}
header: {
html: {
template: 'student/resumes/header',
layout: 'pdf.erb',
handlers: [:erb],
formats: [:pdf]
}}
end
end
end
If there is a extra page in your pdf when pdf generate with wicked pdf, then
Simply put a division at last of your html code (or you may put a div according to your code). like :
<% #questions.each do |question| %>
<% if question.id == #questions.last.id %>
<div></div>
<% end %>
<% end %>
After adding a division in your html.put the following line in your css:
div.alwaysbreak { page-break-before: always; }
div.nobreak:before { clear:both; }
div.nobreak{ page-break-inside: avoid; }
It works for me

Slim Partial with Yield

I have a Slim partial for a widget. The widget has common elements and then some custom content that I want to yield to. What's the correct syntax for that? Here's what I thought would work, but doesn't.
Widget Partial
.container
.title= title
.content
== yield
Page
.page
= render partial: "widget_partial", locals: { title: "Content 1" } do
div Some really awesome content.
= render partial: "widget_partial", locals: { title: "Content 2" } do
span Different but also awesome content.
According to the Action View Overview on partials (section 3.2.3), when you are only using a partial template and locals, you can get away with a minimal approach like this:
(widget partial)
.container
.title
p #{title}
= yield
(Page)
= render "widget_partial", title: "content 1" do
.div
p Some really awesome content.
= render "widget_partial", title: "content 2" do
.div
p Different but also awesome content.
Note that in the partial, itself, you cannot put text directly into a
div, so I added a <p> element.
You should add layout argument in the render. Something like this:
(widget partial)
.container
.title = title
.content
= yield
(page)
.page
= render layout: 'widget_partial', locals: { title: 'Content 1' } do
div Some really awesome content.
= render layout: 'widget_partial', locals: { title: 'Content 2' } do
span Different but also awesome content.
Doc: http://edgeguides.rubyonrails.org/action_view_overview.html#partial-layouts

How can I DRY up conditional content_for in Rails view?

contests/show.html.haml:
- if modal
- content_for(:modal_header) do
= render 'contests/contest_header'
- content_for(:modal_body) do
= render 'contests/contest_body'
- else
= render 'contests/contest_header'
= render 'contests/contest_body'
modal is a boolean local which indicates whether the view is being rendered in a modal template, vs the regular application template. The modal has content_for blocks while the main application template does not:
layouts/modal.html.haml:
-modal = true
.modal-header
.row
.col-xs-11
= yield(:modal_header)
.col-xs-1
%button{'type': 'button', 'class': 'close', 'data-dismiss': 'modal', 'aria-label': 'close'}
%span{'aria-hidden': 'true'} ×
.modal-body
= render 'layouts/messages'
- if content_for?(:modal_body)
= yield(:modal_body)
- else
=yield
What I'm looking for is something that can conditionally make the content_for blocks disable when modal is false. Rather than repeating my render statements.
Found a solution from another SO answer! https://stackoverflow.com/a/27398070/378622
Here's my implementation
# app/helpers/application_helper.rb
def modal_content_for(name, &block)
if params[:modal] == '1'
content_for 'modal_' + name.to_s, nil, &block
else
capture_haml(&block)
end
end

Rails - Know caller filename when using render layout

I want to dynamically add classes to a container based on the name of the class that called my layout using the render method. Is it possible or do I need to pass it manually from each view?
File: emails/inbox.html.haml
render layout: 'shared/v3/panel' do
// whatever
Rendered HTML:
<div id="inbox" class="panel email_container"></div>
My temp solution is to do:
render layout: 'shared/v3/panel', locals: {class_panel: 'email_container', id_panel: 'inbox'} do
// whatever
But I want to do that dynamically.
Final solution: views/shared/_panel.html.haml
- # You need to use: "render layout", not "render partial" to pass the "do" block.
.container_content{class: "#{controller_name}_container #{local_assigns[:panel_class] ? panel_class : ''}", id: action_name}
- if local_assigns[:title]
.headline= local_assigns[:title]
= yield
- if local_assigns[:footer]
.footer= local_assigns[:footer]
- # Example of use:
-#= render layout: 'shared/v3/panel', locals: {title: 'Place', panel_class: 'my_custom_class'} do
-# - if #activity.place.present?
-# %p
-# = t('place')
-# = #activity.place

Nested render partials in Rails3 with HAML

I am attempting the following
A HAML template with
#whitepanelMID
#groups_view_scroller
= render 'show' do
= render 'short_field', locals: {label: 'Name:', value: #group.name}
= render 'short_field', locals: {label: 'Description:', value: #group.description}
And the partials are _show.html.haml (note the use of yield)
%table#vert_table.no_borders{ cellpadding: '0', cellspacing: '0'}
%tbody
%tr
%td{ cols: 2 } My table
= yield
and _short_field.html.haml
%tr
%th.vert_table_heads= label
%td= value
The issue is that yield does not seem to work.
What's the proper way to use block in render in HAML?
Update
I found a workaround, which I don't like.
In the HAML template capture the output like
#whitepanelMID
#groups_view_scroller
- rows = capture_haml do
= render partial: 'short_field', locals: {field_label: 'Name:', value: #group.name}
= render partial: 'short_field', locals: {field_label: 'Site:', value: #group.site.description}
= render partial: 'show', locals:{ content: rows}
%br/
with the modified partial _show.html.haml with a content variable instead of yield
%table#vert_table.no_borders{ cellpadding: '0', cellspacing: '0'}
%tbody
%tr
%td{ cols: 2 } My table
!= content
Happy to hear a better approach!
Just because the link provided by #vidaca is ERB, I want to post an equivalent for HAML.
Use layout: when using the wrapper template
#whitepanelMID
#groups_view_scroller
= render layout: 'show', locals:{ table_title: 'My table'}
= render partial: 'short_field', locals: {field_label: 'Name:', value: #group.name}
= render partial: 'short_field', locals: {field_label: 'Site:', value: #group.site.desccription }
%br/
and _show.html.haml partial (wrapper) like
%table#vert_table.no_borders{ cellpadding: '0', cellspacing: '0'}
%tbody
%tr
%td{ cols: 2 }= table_title
= yield
the wrapped partials (short_field in this case) work as-is.
Hope helps someone.

Resources