How to inject active_admin header into custom layout? - ruby-on-rails

I'm try to custom active_admin layout for specific action.But I dont know how can i add active_admin's header into my custom layout?
app/admin/provider.rb
I render edit page with custom_active_admin layout
controller do
def edit
#provider = Provider.find(params[:id])
render 'admin/providers/edit', layout: 'custom_active_admin'
end
...
end
app/views/admin/providers/edit.html.haml
= semantic_form_for ...
= f.inputs 'Location', for: :location do |location|
= location.input :postal_code
= location.input :prefecture
app/views/layouts/custom_active_admin.html.haml
I'm try to custom layout for my special action
!!!
%html
%head
= csrf_meta_tags
= csp_meta_tag
...
= stylesheet_link_tag 'custom_active_admin', media: 'all'
= javascript_include_tag 'custom_active_admin'
%body.new.active_admin.logged_in.admin_namespace
#header
= yield :head
.wrapper.without_sidebar#active_admin_content
.main_content_wrapper
.alert-message-container
= yield
My custom action can work fine. But i need add header to top page like those pages using default active_admin layout. How i can do it? Thanks.

You can register custom stylesheets and javascript in the config initializer. I recommend just adding the CSS & JS into your active admin config:
# config/initializers/active_admin.rb
# == Register Stylesheets & Javascripts
#
# We recommend using the built in Active Admin layout and loading
# up your own stylesheets / javascripts to customize the look
# and feel.
#
# To load a stylesheet:
config.register_stylesheet 'my_stylesheet.css'
#
# You can provide an options hash for more control, which is passed along to stylesheet_link_tag():
# config.register_stylesheet 'my_print_stylesheet.css', media: :print
#
# To load a javascript file:
config.register_javascript 'my_javascript.js'
If you feel strongly that the JS should only be on that single view, you can include it in the view itself.
for example, in an app I have, we display charts on 1 page of active admin, and have included the chart library at the top of the view:
= javascript_include_tag "//www.google.com/jsapi", "chartkick"
%h2 History chart
= line_chart participant.linear_chart_payload, curve: false
The script goes in the body, which is not ideal, but it works fine. I don't think there's a need to put CSS in the view itself, as you should be able to use selectors to ensure that the CSS only applies to the view you need it to.

Related

using a different style for different views in rails

Rails 5.1
I mostly work on backend issues, but I am trying to learn more about front end stuff, and I am a little confused about how styles are handled in Rails (I read through a bunch of answers on stackolverflow, but that did not help narrow it down for me).
I have two different views
views/user/login.html.slim
views/user/new.html.slim
I would like to apply different body styles to each view. When the application was generated, Rails added:
assets/stylesheets/users.css.scss
Would I need to add a folder, called users and inside it, have different stylesheets? something like this:
assets/stylesheets/users/login.css.scss
would have in it:
body {
padding-top: 40px;
}
and
assets/stylesheets/users/new.css.scss
would have in it:
body {
padding-top: 80px;
}
Then, in
stylesheets/application.css.scss
I would add:
*= require_self
*= require_tree .
The styles and javascripts are loaded from your layout. Out of the box it looks like this:
app/views/layouts/application.html.erb
<%= stylesheet_link_tag 'application', media: 'all' %>
<%= javascript_include_tag 'application' %>
If you only want to include particular css files in a particular view, you would need to:
Create a layout for your particular view.
Include the appropriate styles and javascripts in the layout.
Specify the particular layout in your controller.
Here is some more information on layouts, but lets go through it for your login example.
app/controllers/sessions/create
class SessionsController < ApplicationController
layout 'login', only: [:new]
# you could also call the layout "sessions.html.erb" and it will be
# loaded automagically
If you want to use a different layout for different actions in the same controller, you can add other layout methods and specify the actions they apply to with the only action.
Then the layout
app/views/layouts/login.html.erb
...
<%= stylesheet_link_tag 'login', media: 'all' %>
...
And finally your stylesheet
app/assets/stylesheets/login.scss
#import "file_you_want";
If you require_tree . it will load all styles in the stylesheets directory which I don't think is what you are after.

different css for index action in rails 5 bootstrap 4 (single controller)

I am using a specific bootstrap 4 template for my application. This template (cover.css) is specific to the homepage as all the others pages will use a different style.
How can I use cover.css only for the index action?
In my application.css I added #import "cover" can I have this only applied to the index action?
I tried creating two layouts instead: application.html.erb to use it for the application, and a second layout home.html.erb just for the home page. How can I associate cover.css for only the index action and have my dashboard layout and css for the rest of the application?
I am using rails 5 and bootstrap 4 alpha.
There are a few ways to accomplish this.
You can create a layout which includes the cover.css asset, and then only apply the layout for the index action as described here Rails layouts per action?
class MyController < ApplicationController
layout :resolve_layout
# ...
private
def resolve_layout
case action_name
when "new", "create"
"some_layout"
when "index"
"other_layout"
else
"application"
end
end
end
Another option would be to use a single layout and scope your styles.
In views/layouts/application.html.erb Set classes on the body tag like this
<body class="<%= controller_name %> <%= action_name %>">
When rendered it will output
<body class="home index">
Then in your cover.css scope your styles to the .home.index selector
body.home.index h1{
/* this style is only applied on the home/index page */
}
Something like this will work.
<%= stylesheet_link_tag "application", :media => "all" %>
<%= stylesheet_link_tag params[:controller] %>
See the 3rd answer here: How do I use Controller specific stylesheets in Rails 3.2.1?

RoR stylesheet layout view link. What does `:media => all` mean

I have:
<&= stylesheet_link_tag "application", :media => "all" %>
but I am adding a (completely) alternative layout for some of the views in my application, with separate stylesheets. I would like to link the existing layout to only some of the stylesheets, and add others. What do I need to change here?
for this you can create new file in views/layout as similar to your application.html.erb
for example i am creating home.html.erb.Link your all stylesheets and js files in that and finally just add that layout name in your required controller as layout 'home'
You can use separate manifest file and include those manifest file
This answer will help you how to do this
It specifies that your application.css should be loaded when the page is viewed in all media types. It's a CSS property, not a Rails property.
See http://www.w3.org/TR/CSS2/media.html#media-sheets for more details.
You can add a separate layout for whole controller or for specific actions
For example:
in your controller:
layout :resolve_layout
#controller code
...
def resolve_layout
case action_name
when "new", "create", "wait_conformation"
"customer_layout"
else
"producer_layout"
end
end
Here customer_layout & producer_layout are layout files.

how do I call the asset_pipeline for only 1 file?

I'm trying to understand the asset_pipeline.
I basically have all my website-wide code in style.css.scss (which is #imported in application.css.scss)
I also have a few miscellaneous controllers that have code that I split off into a separate file only to be loaded on that page. For example, in my profiles_controller I have profiles.css.scss and profiles.js
in the documentation it says i can conditionally include those by typing:
<%= stylesheet_link_tag params[:controller] %>
and a similar one for javascript_include_tag
The problem is when i view source on any of my pages that dont have a controller stylesheet it is a 404 file not found. I dont want to have 10 blank files for each controller and 10 blank javascript files (those controllers have hardly any extra css or code, so i put it in the main scss file) ... am i doing this wrong?
Note:I have removed include tree from the JS and css files, as i dont want any file in that folder being included
In your application layout file, add yield statements like this to pull in the stylesheets you include as one-offs in different views:
= stylesheet_link_tag "application"
= yield :stylesheets
= javascript_include_tag "application"
= yield :javascripts
Then in each view file where you want to include stylesheets:
= content_for :stylesheets do
= stylesheet_link_tag "controller_name"
= content_for :javascripts do
= javascript_include_tag "controller_name"
This will include those files in only the views you need them in.

How can I customize the active admin layout?

I need to customize the active admin layout, but how can I do it?
The active admin layout is not actually defined as a layout file, but is generated programatically. Placing a custom layout in the layout directory will therefore not actually override the default layout.
You can, however, monkey-patch or duck-punch the active admin layout methods inside your application.
The following will add an ie-specific stylesheet to the header:
module ActiveAdmin
module Views
module Pages
class Base < Arbre::HTML::Document
alias_method :original_build_active_admin_head, :build_active_admin_head unless method_defined?(:original_build_active_admin_head)
def build_active_admin_head
within #head do
meta :"http-equiv" => "Content-type", :content => "text/html; charset=utf-8"
insert_tag Arbre::HTML::Title, [title, active_admin_application.site_title].join(" | ")
active_admin_application.stylesheets.each do |path|
link :href => stylesheet_path(path), :media => "screen", :rel => "stylesheet", :type => "text/css"
end
active_admin_application.javascripts.each do |path|
script :src => javascript_path(path), :type => "text/javascript"
end
text_node csrf_meta_tag
text_node "<!--[if lt IE 7]>
<link rel=\"stylesheet\" type=\"text/css\" media=\"all\" href=\"admin_ie7.css\ />
<![endif] -->".html_safe
end
end
end
end
end
end
Clearly an ugly solution.
When a view is defined in a gem AND in the rails app, the one defined in the Rails app is served. It's a logic priority.
So if you need to override all or some active admin views, you'll have to copy these in your app and change them as you desire.
Maybe ActiveAdmin does provide a nicer way to do this by now? I don't know.
However here would be an example for a bit cleaner patch for that situation, in my example to add the webpacker gems javascript_pack_tag to my admin area.
module MyApp
module ActiveAdmin
module Views
module Pages
module BaseExtension
def build_active_admin_head
super
within #head do
text_node(javascript_pack_tag('application'))
end
end
end
end
end
end
end
class ActiveAdmin::Views::Pages::Base < Arbre::HTML::Document
prepend MyApp::ActiveAdmin::Views::Pages::BaseExtension
end
(Using rails 5.1.4) I tried two solutions here that involved messing with the active_admin library, and they did not work for me at all. I found my solution in config/initializers/active_admin.rb. I am adding a small amount of bootstrap styling to the default layout. As far as linking to stylesheets, javascripts, etc., it was as simple as adding this to my active_admin.rb, as per the comments therein:
# == Register Stylesheets & Javascripts
#
# We recommend using the built in Active Admin layout and loading
# up your own stylesheets / javascripts to customize the look
# and feel.
#
# To load a stylesheet:
# config.register_stylesheet 'my_stylesheet.css'
config.register_stylesheet 'https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css', { integrity: 'sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk', crossorigin: 'anonymous' }
As far as editing that generated layout, I have yet to figure it out, but it could at least be done indirectly via JavaScript and the inclusion of that javascipt in this file via
config.register_javascript 'active_admin_view_tweaks.js', { defer: true }
I am going to be editing class attributes to make my pages responsive with bootstrap, so I might follow something like this geeksforgeeks article to edit the pages with JavaScript after they've loaded.
I don't know if there is a way to edit the generated layout more directly, but this should work for some cases.
You can override the active admin page layout by putting the following code in your config/intializers/active_admin.rb file:
module AdminPageLayoutOverride
def build_page(*args)
within super do
render "shared/your_custom_view_partial"
end
end
end
ActiveAdmin::Views::Pages::Base.send :prepend, AdminPageLayoutOverride
In the above example, I have a custom view file at app/views/shared/_your_custom_view_partial.html.erb location and I am injecting that in all of my active admin pages by the above code.

Resources