Getting URL inside of EJS layout template? - express

My goal is to create a conical URL in the head of my layout doc in .ejs
https://en.wikipedia.org/wiki/Canonical_link_element I'd like to do something like the following where I check URL structure and then change how I format that, but I'm assuming the window object doesn't exist at this stage in EJS while it's being templated. I know I could pass the URL on route, but it's a bit late for that and I'm wondering if there's a way I could do this or something like it in the head section of my layout?
<% if(window.location.href.indexOf("review")){ %>
<link rel="canonical" href="https://www.example.com/bestTools" />
<% } else{ %>
<link rel="canonical" href="<% window.location.href %>" />
<% } %>

Related

How can I render section in a children Partial view?

The runtime&SDK I am using is the newest version .net 6
Here are three Partial views in _Layout.cshtml of my project: header.cshtml/aside.cshtml/footer.cshtml .
Why I speared them to three parts for there are so many codes for them that I have to speare for coding convenient.
Now I need to add a section to the header.cshtml. Here is my code:
<header>
///some other codes
#RenderSection("ProductNav", required: false)
</header>
No matter there is a section "ProductNav", after the program ran, the page will all be blank without any error.
I found that it seems I can not use the RenderSection in a children Partial view.
It seems there is another way by using the Html.Partial to achieve this.
However, it needs to convert the views that I want to add to string. That's so troublesome.
Is there an easy way can achieve this? Thank you.
You want to show navbar on partial pages, You use partial view to achieve this function, But user can't add css style in partial view directly.
My idea is you can create a External CSS file in wwwroot and use it in page whitch needs to load partial view.
I write a demo to demonstrate the feasibility of this idea.
Views/Shared/_header.cshtml
<h2>This is head Partial View H2</h2>
<p>This is head Partial View P</p>
wwwroot/css/header.css
h2 {
color: blue;
}
p {
color: red;
}
views/Shared/_Layout.cshtml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>#ViewData["Title"] - EmptyNEt5MVc</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" />
//add the css file in here
#await RenderSectionAsync("Css", required: false)
</head>
//.........
View
#{
ViewData["Title"] = "Privacy Policy";
}
//use partial view
<partial name="_header" />
<h1>#ViewData["Title"]</h1>
<p1>Use this page to detail your site's privacy policy.</p1>
//reference css file
#section Css{
<link rel="stylesheet" href="~/css/header.css" />
}
Then you can see the `header partial view' load the css file successfully
=============================================
In fact, View Component is more suitable for navigation bar than Partial View, There is a document about View Component.

on layout:false losing client_side_validation properties

I am rendering partial on click using jquery. Here is the code for it
$('.actCell').click(function (){
alert('Load was performed.');
$.get('/policies/new', function(data) {
$('.policyAddForm').html(data);
});
});
Here is the controller code
def new
#policy = Policy.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #policy }
end
end
This is my application.html
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Passport</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<%= stylesheet_link_tag "application", :media => "all" %>
</head>
<body>
<div class="header">
<div class="container">
<img src="/assets/ph_logo.png">
<div class="user"><%=current_user.email%> <div class="userDrop"></div></div>
<div class="userDropMenu">
<div class="userActRow">change password</div>
<div class="userActRow">sign out</div>
</div>
</div>
</div>
<div class="nav">
<div class="container">
<%= yield %>
</div>
</div>
<%= javascript_include_tag "application" %>
<%= yield :javascript %>
</body>
</html>
With above code the problem is my layout get messed up. Div I updated with partial form shows header so it is layout in a layout but my client_validation_gem properties work. as soon as I say layout false my layout issue get fixed but I lose the client_side_validation gem properties. I dont know what is the issue and I am really frustrated. Any help or direction will be very helpful. Thanks,
Looks like you're not loading the rails.validations and rails.validations.custom js files if you use layout: false. You may have to include them in the partial (something like this).
= javascript_include_tag 'rails.validations'
Edit
Just saw that you're adding the form dynamically. You'll also need to trigger client-side validations like this after adding the form:
$('form[data-validate]').validate();
Finally I figured out. I have to remove rails.validations.js file because it was outdated. And add '$('form[data-validate]').validate();' to js file as #David suggested. Thanks for help

express can't serve static file for child ejs file

express version is 3.2.5, ejs version is 0.8.4
I want to serve stylesheets/style.css
I am doing this way in app.js
app.use(express.static(path.join(__dirname, 'public')));
app.use(app.router);
// render article.ejs
app.get('/u/:name/:day/:title', function(req,res){
Post.getOne(req.params.name, req.params.day, req.params.title, function(err, post){
if(err){
req.flash('error',err);
return res.redirect('/');
}
res.render('article',{
title: req.params.title,
post: post,
user: req.session.user,
success: req.flash('success').toString(),
error: req.flash('error').toString()
});
});
});
my structure is header.ejs
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Blog</title>
<link rel="stylesheet" href="stylesheets/style.css">
</head>
<body>
article.ejs content is
<%- include header %>
<p class="info">
author:<%= post.name %> |
date:<%= post.time.minute %>
</p>
<p><%- post.post %></p>
<%- include comment %>
<%- include footer %>
When I access http://localhost:3000/
GET /stylesheets/style.css 304 9ms
while access localhost:3000/u/username/date/postname
GET /u/username/date/stylesheets/style.css 404 10ms
why it shows this /u/username/date/stylesheets/style.css directory
Any ideas?
You don't start your stylesheets path with a /. So it's loading "stylesheets/style.css" relative to whichever HTML file requested it.

express js - ejs with layout template

In my express app,
I've changed the view engine to ejs.
Does anyone know if it is still possible to take advantage of view templates?
Actually after Express 3.X is not support layout.ejs, if you want to use the layout, following steps should be done by yourself:
add dependency "express-partials": "*" in you package.json file
"dependencies": {
"express": "3.1.0",
"ejs": "*",
"express-partials": "*"
}
execute npm install to install the latest version of express-partials
require express-partials in your app.js
var partials = require('express-partials');
add code app.use(partials()); under the app.set('view engine', 'ejs'); in app.js file
after that, you can design you layout.ejs and add <%- body%> block in your layout.ejs file, and that's enough and working well.
You can do it with this module...
https://github.com/aseemk/express-blocks
layout.ejs
<html>
<body>
<% include nav %>
<h1><%= title %></h1>
<%- body %>
</body>
</html>
login.ejs
<% layout('layout') -%>
<form>...</form>
nav.ejs
<nav>
<% if ( session.logged_in ) { %>
account
logout
<% } else { %>
signup
login
<% } %>
home
</nav>
I was using express-partials, but I found express-blocks to be better for ejs and express 3.x. using partials was a pain to have to pass data in everytime. With <% include whatever %> the data is already accessible.
In your routes file, you can render like this:
exports.login.get = function(req, res){
res.locals.session = req.session;
res.render('login', { title: 'Login to your account' });
};
Express.js leaves that up to the template engine if I remember correctly. So if ejs doesn't support layouts then you are out of luck.
Install ejs-blocks package npm install ejs-blocks
In your app.js file import the package const engine = require('ejs-blocks');
and configure view engine
//settings
app.set('views', path.join(__dirname, 'views'));
app.engine('ejs', engine);
app.set('view engine', 'ejs');
In express by default the name of the file is layout.ejs So create a file called layout.ejs in your views folder with the next content:
views/layout.ejs
<html>
<head>
<title><%= title %></title>
</head>
<body>
<%- body %>
</body>
<%- blocks.js %>
</html>
<%= title %> value is obtained when the file is called from route
router.get("/", (req, res) => {
res.render("index", { title: "Hello world!" });
});
Each of your views must import the layout.ejs file in the first line, for example
views/index.ejs
<% layout('layout') -%>
<h1>Article title</h1>
<p>Content</p>
...
<% block('js', `<script>
...
</script>`) -%>
You can use block for insert code from the view to the main layout.

Add Dynamically Links to jQuery Mobile

I read a lot about how to add stuff dynamically in jquery mobile, but I couldn't figure out how to add links.
Currently my solution looks like this:
Add a new Page - with id (id="list-1")
Creating a Link for it (href="#list-1")
This solution works perfectly in static pages, but I want to do it dynamically. I have tried a lot with page() and stuff like that but nothing helped me.
My questions are:
How do I add dynamic links & pages?
Did I choose the right way to use ids & anchors (#list-1) as links or is there another solution for jquery mobile?
Let me know if you need more information
To add dynamic links, I have found the easiest way is to just have an event listener waiting for a click on those links. This event listener then saves any parameters you want to pass into the next page you are visiting. You pass the parameters from the list element to the event listener by just specifying parameters within each "li" element.
(create the HTML for a list dynamically & store it into list-1-html)
$("div#my-page div[data-role=content]").html(list-1-html);
$("div.list-1 ul").listview();
$("div.list-1 ul").listview('refresh');
Then your event listener would look something like:
$('#my-page').delegate('li', 'click', function() {
passedParameter = $(this).get(0).getAttribute('passed-parameter');
});
When jQuery Mobile loads your next page, you'll probably want to load this page dynamically and you'll have this passedParameter variable available to you. To load the page dynamically, just add a listener that waits for JQM to try to load the page:
$('[data-role=page]').live('pageshow',function(e, ui){
page_name = e.target.id;
if (page_name == 'my-page-2'){
(do something with passedParameter)
}
});
This is the workflow I use with jQuery Mobile and it has been working just fine. I'm guessing in future releases, though, that they'll build in some kind of support for passing dynamic parameters to pages.
Any new enhancement to the DOM should be done before the page initializes. But by default JQM automatically initializes the page once the page is load in browser.
Hence first you need to set autoInitializePage property to false and then call initializePage() method after the new page and links are add to the document. Hope this helps.
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css" />
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script>
$(document).bind("mobileinit", function(){
$.mobile.autoInitializePage = false;
});
</script>
<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>
<script>
$(document).ready(function() {
//add a link.
$("#page1 div[data-role='content']").append('Next Page');
//add a page.
$('body').append(' <div data-role="page" id="page2" data-title="next page"><header data-role="header" class="header"> <h5>Page 2</h5></header><div data-role="content"><h3>Good Morning...</h3>Back</div><footer data-role="footer" data-position="fixed"><h5>© All rights reserved</h5></footer></div>');
});
window.onload = function() {
$.mobile.initializePage();
};
</script>
</head>
<body>
<div data-role="page" id="page1">
<header data-role="header" class="header">
<h5>jQuery Mobile</h5>
</header>
<div data-role="content">
<form method="get" action="" data-transition="slideup">
<label for="email">Email:</label>
<input type="email" name="email" id="email" value=""/>
</form>
</div>
<footer data-role="footer" data-position="fixed"><h5>© All rights reserved</h5></footer>
</div>
</body>
</html>