Rendering wrong head with login layout - layout

Can anyone tell me how it is possibile that the following layout in a Rails 4 app
# app/views/layout/login.html.erb
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
<title>PIPPO</title>
<meta content="yes" name="apple-mobile-web-app-capable">
<meta content="black-translucent" name="apple-mobile-web-app-status-bar-style">
<meta name="viewport" content="initial-scale = 1.0,maximum-scale = 1.0" />
<link href="/assets/login.css" media="all" rel="stylesheet" />
<script src="/assets/login.js"></script>
<%= csrf_meta_tags %>
</head>
<body>
<div class="main-content">
<%= yield %>
</div>
</body>
</html>
With the following controller
class SessionsController < ApplicationController
layout 'login'
...
def destroy
Session.find(session[:id]).close
reset_session
respond_to do |format|
flash[:success] = t('sessions.logout')
format.html { redirect_to login_url }
end
end
end
and routes
...
get 'login', to: 'sessions#new', as: 'login'
get 'logout', to: 'sessions#destroy', as: 'logout'
...
produces the following HTML once I click on <%= link_to 'logout', logout_path %>?
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
<title>PIPPO</title>
<meta content="yes" name="apple-mobile-web-app-capable">
<meta content="black-translucent" name="apple-mobile-web-app-status-bar-style">
<meta name="viewport" content="initial-scale = 1.0,maximum-scale = 1.0" />
<link href="/assets/application.css" media="all" rel="stylesheet" />
<script src="/assets/application.js"></script>
<meta content="authenticity_token" name="csrf-param" />
<meta content="l9+umk+wjpXY4UFiKEeuQkGgMvjbbZ2uDxyJHowTJFo=" name="csrf-token" />
</head>
Am I missing anything here? It is two days I'm trying to figure this out.
Why is it using the head from the main layout instead of the one in login?
Thanks for your help.
UPDATE - Forgot to mention my log file states:
Rendered sessions/new.html.erb within layouts/login (1.4ms)

As per the layout name given in the question, i.e.,
app/views/layout.login.html.erb
There are couple of things wrong here:
layouts should be placed in app/views/layouts folder
File name should be login.html.erb and not layout.login.html.erb
In your case, Rails could not find login.html.erb in app/views/layouts, it rendered the default layout app/views/layouts/application.html.erb.

Related

Chartist not defined error in Node / express app

I am trying to use Chartist in a Node app using ejs to render my HTML . I am using the Chartist CDN and have included the necessary scripts etc in my header.ejs and set up my data model in the main.ejs file I want to render. However I keep getting "Chartist not defined error". I have tried moving the script tag into my footer, as per another answer on SO, but that didn't work either. My header.ejs and main.ejs are as follows. Is there something I am missing?
header.ejs:
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="stylesheets/styles.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/chartist.js/latest/chartist.min.css">
<script src="https://cdn.jsdelivr.net/chartist.js/latest/chartist.min.js"></script>
</head>
<body>
And main.ejs
<%- include('partials/header') %>
<h1>GRAPH</h1>
<div class="ct-chart ct-perfect-fourth"></div>
<% let data = {
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
series: [
[5, 2, 4, 2, 0]
]
};
%>
<% new Chartist.Line('.ct-chart', data); %>
<%- include('partials/footer') %>

EJS/Node/Express - Having a header partial, how to change title for each page?

I recently took a course on back-end web developing.
As the title says, I don't get how can I use a header partial for the whole website but have different titles for each page. (because is included in the tag)
Is there any trick?
1st) In your Express route:
app.get("/", function(req, res){
res.locals.title = "Abel's Home Page"; // THIS LINE IS KEY
res.render("home.ejs");
});
2nd) In your views/home.ejs file:
<% include partials/header.ejs %>
3rd) In your views/partials/header.ejs file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title><%= title %></title> <!-- THIS LINE IS KEY -->
<link rel="stylesheet" href="../style.css">
<link rel="shortcut icon" href="../logo_sm.png" type="image/x-icon">
</head>
<body>
Each page that includes the partial is free to pass data to said partial through parameters. See here for an example.

Thymeleaf layout dialect and th:replace in head causes title to be blank

I'm following this tutorial: http://www.thymeleaf.org/doc/layouts.html (got to Thymeleaf Layout Dialect section).
In there you can find an example:
<!DOCTYPE html>
<html>
<head>
<!--/* Each token will be replaced by their respective titles in the resulting page. */-->
<title layout:title-pattern="$DECORATOR_TITLE - $CONTENT_TITLE">Task List</title>
...
</head>
<body>
<!--/* Standard layout can be mixed with Layout Dialect */-->
<div th:replace="fragments/header :: header">
...
</div>
<div class="container">
<div layout:fragment="content">
...
</div>
<div th:replace="fragments/footer :: footer">© 2014 The Static Templates</div>
</div>
</body>
</html>
Footer and header are replaced by th:replace tag in above example, while <head> has <title> tag in layout file.
Basically, I want to replace whole <head> tag with th:replace.
Therefore, I have:
My layout file:
<!DOCTYPE html>
<html>
<head th:replace="/html/components/head :: head">
</head>
<body>
<div layout:fragment="content">
</div>
...
<div th:replace="/html/components/footer :: footer" />
</body>
<html>
My content file:
<!DOCTYPE html>
<html layout:decorator="/html/layouts/layout">
<head>
<title>My content title</title>
</head>
<body>
<div layout:fragment="content">
...
</div>
</body>
</html>
And finally my /html/components/head.htm file:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head th:fragment="head">
<meta charset="utf-8" />
<title layout:title-pattern="$CONTENT_TITLE">Layout Title should be replaced by Content Title!</title>
...
</head>
<body>
</body>
</html>
Content is alright. Footer and head are included (replaced) from files as expected but page title is blank!
I get:
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<title></title>
...
What's wrong?
Finally, I've found a way to achieve what I wanted.
In layout file <title> tag must stay. All other tags I grouped with <object> tag and annotated it as follows:
<head>
<title layout:title-pattern="$CONTENT_TITLE">Layout Title will be replaced by Page Title!</title>
<object th:include="/html/components/head :: head" th:remove="tag" />
</head>
In my html/components/head.htm file I had to remove <title> tag so it won't be duplicated after include.
<head th:fragment="head">
<meta charset="utf-8" />
<!-- NO TITLE TAG HERE -->
...
</head>
This way head fragment is included in <object> tag and thanks to th:remove="tag" <object> tag gets removed and my final HTML output is:
<head>
<title>My content title</title>
<meta charset="utf-8" />
<!-- NO TITLE TAG HERE -->
...
</head>
Obviously, I removed NO TITLE TAG HERE message too, once I got it working.
I think I found a slightly less verbose way to for using th:replace and th:fragment together, e.g. to include common <head> metadata and static resource includes in your pages.
Put the th:remove="tag" in the fragment definition, so you don't have to repeat the th:remove="tag" everytime including it.
fragment_head.html
<thymeleaf xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
th:fragment="head" th:remove="tag">
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" th:href="#{/css/vendor/bootstrap.min.css}"/>
</thymeleaf>
mypage.html
<head>
<thymeleaf th:replace="fragment_head :: head" />
</head>
You can replace whole head tag.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head lang="pl" th:replace="fragments/head :: head">
</head>
<body>
...
</body>
</html>
resources/templates/fragments/head.html:
<head lang="pl">
<title>Title</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link href="http://cdn.jsdelivr.net/webjars/bootstrap/3.3.5/css/bootstrap.min.css"
th:href="#{/webjars/bootstrap/3.3.5/css/bootstrap.min.css}"
rel="stylesheet" media="screen" />
<script src="http://cdn.jsdelivr.net/webjars/jquery/2.1.4/jquery.min.js"
th:src="#{/webjars/jquery/2.1.4/jquery.min.js}"></script>
<link href="../static/css/mycss.css"
th:href="#{css/mycss.css}" rel="stylesheet" media="screen"/>
</head>

Add Meta tag in View page using MVC-5

I have two meta tag in _Layout.cshtml master page and now i want to add meta tags in someone.cshtml view page.
and i also try with this code
put in _layout.cshtml master page #RenderSection("metatags",false);
put in someone.cshtml like #section metatags { <meta ... /> }
but not get success.
and also try with add meta tag jquery but not worked fine.
It should work.
Here's my master page _Layout.cshtml
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
#RenderSection("metatags", false)
<title>My ASP.NET Application</title>
</head>
<body>
#RenderBody()
</body>
</html>
Here's the index.cshtml file
#section metatags
{
<meta name="test" content="test"/>
<meta name="test2" content="test"/>
}
<div>Page content</div>
The result
<html>
<head>
<meta charset="utf-8">
<meta name="test" content="test">
<meta name="test2" content="test">
<title>My ASP.NET Application</title>
</head>
<body>
<div>Page content</div>
</body>
</html>
I found a way that works for now.
This solution mostly use when multiple master page.
In the controllers / action assign whatever meta info you need for that view.
ViewBag.Title = "some title";
ViewBag.MetaDescription = "some description";
In the View or master page get whatever meta info you need for that view.
#if(ViewBag.MetaDescription != null)
{
<meta name="description" content="#ViewBag.MetaDescription" />
}
#if(ViewBag.MetaKeywords != null)
{
<meta name="keywords" content="#ViewBag.MetaKeywords" />
}
If are using nested layouts you'll need to follow this guideline:
#RenderSection in nested razor templates
The technique you're using should work, if it is not, maybe that's the reason.
But looking at the intended use in your own answer, if you only need to modify the keywords and description tags there are apis in NopCommrece for that.
In your master layout:
<meta name="description" content="#(Html.NopMetaDescription())" />
<meta name="keywords" content="#(Html.NopMetaKeywords())" />
and in the client cshtml files
#{
Html.AddMetaDescriptionParts(Model.MetaDescription);
Html.AddMetaKeywordParts(Model.MetaKeywords);
}
There are plenty of samples for this in the NopCommerce code.
here is a good sample on how to dynamically creating meta tags in asp.net mvc:
public string HomeMetaTags()
{
var strMetaTag = new StringBuilder();
strMetaTag.AppendFormat(#"<meta content='{0}' name='Keywords'/>","Home Action Keyword");
strMetaTag.AppendFormat(#"<meta content='{0}' name='Descption'/>", "Home Description Keyword");
return strMetaTag.ToString();
}
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
ViewBag.MetaTag = HomeMetaTags();
return View();
}
<head>
<title>#ViewBag.Title</title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
#Html.Raw(ViewBag.MetaTag)
</head>

How to prevent layout rendering when following a link

I have a view that should not be using a layout.
This is the controller action used :
def last
#video = Video.last
render layout: false
end
When I call the "show" view directly, it works, no layout are used.
Nonetheless, when I call that view by following a link then it actually loads the default layout with my view.
the link is present in a layout :
<%= link_to "last video", last_video_path %>
and the view :
<body marginwidth="0" marginheight="0">
<iframe type="text/html" width="100%" height="100%" frameborder="0"
src="http://www.youtube.com/embed/<%= #video %>" >
</iframe>
</body>
Any idea what I might be doing wrong ??
I finally found what was not working. In my layout, I have in the header :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= content_for?(:title) ? yield(:title) : "NBATopOfTheNight" %></title>
<%= csrf_meta_tags %>
<%= stylesheet_link_tag "application", :media => "all" %>
<%= javascript_include_tag "application" %>
</head>
<body>
...
the line <%= javascript_include_tag "application" %> is added by twitter bootstrap and is responsible for rendering my views even when I specify no rendering.
Deleting this line make my project works :-)

Resources