How to include external .js file to ejs Node template page - node.js

I cannot find a way to include external .js file to Node ejs template. I want to put logic and data into object in external .js file, include that file to index.ejs template and pull data from it.
I tried by inserting standard way
<script src="sample.js"></script>, and it doesn't work
Then I tried ejs specific keyword <% include partials/sample.js %> and this works only for adding partials (ejs code snippets).
I inserted .js file into static directory which is defined in executable server.js, no results again.
But interestingly, including css file into ejs template classic way works fine, for example
<link href="/assets/styles.css" rel="stylesheet" type="text/css" />
Workaround would be to include external ejs file where I would put logic and data inside <% %> tags, but this is obviously a patch and not a viable solution, because ejs is not a js file. Besides, it doesn't work.
I cannot find any solution on Internet. Any hint?
Thanks

You can't.
Note: You can only pass data from .ejs file to .js file but not the other way. It won't work because .ejs is rendered on the server side while .js runs on the client side.
I am assuming you are using EJS on server side
1) You can pass an ejs variable value to a Javascript variable
<% var test = 101; %> // variable created by ejs
<script>
var getTest = <%= test %>; //var test is now assigned to getTest which will only work on browsers
console.log(getTest); // successfully prints 101 on browser
</script>
2) You can't pass a js variable value to a ejs variable
Yes, you can't: if it is on server.
Why:
The EJS template will be rendered on the server before the js is started execution(it will start on browser), so there is no way going back to server and ask for some previous changes on the page which is already sent to the browser.

A workaround with Express:
myScripts.js
module.export = {
foo() {},
bar() {}
}
Then in your app.js
var myScripts = require('/path/to/myScripts');
res.render('template', {
utils: myScripts
}); // you forgot a ')' here
then in your template.ejs
// utils will act in global scope for this file
<%
utils.foo();
utils.bar();
%>

I believe you are using it contrary to the intent.
In a controller you can define external scripts and styles you want to include like so
res.render('page-one', {
title: 'Page One',
data: pageData,
libs: ['page-one', 'utils'],
styles: ['page-one']
});
In your static assets for your app you have a js folder and a css folder
|- static/
|- css/
|- fonts/
|- img/
|- js/
favicon.ico
|- templates/
In your js folder you place the file page-one.js and utils.js
In your css folder you place the file page-one.css
In the head section of your html in the ejs template
<!-- styles included on all pages -->
<link rel="stylesheet" href="/css/bootstrap.css">
<!-- styles specific to individual pages -->
<% if (typeof styles !== 'undefined') { %>
<% if (styles.length > 0) { %>
<% for (let style of styles) { %>
<link rel="stylesheet" href="/css/<%= style %>.css">
<% } %>
<% } %>
<% } %>
Typically it is best practice to include scripts at closing body tag so they don't block page render so before the closing body tag in your ejs file
<!-- scripts included on all pages -->
<script src='/js/libs/jquery.min.js' type='text/javascript'></script>
<!-- page specific scripts -->
<% if (typeof libs !== 'undefined') { %>
<% for (let lib of libs) { %>
<script src='/js/<%= lib %>.js' type='text/javascript'></script>
<% } %>
<% } %>
</body>
When your page renders it will render the script and CSS includes automatically
The if block is in case you don't define any includes in the controller.
In your Express application you define your static and external script includes like so
Remember up above we created js and css folders inside a directory named static
// Define static assets
app.use(express.static('static'));
// included on all pages
app.use('/js/libs', express.static(path.join(process.cwd(), 'node_modules/jquery/dist'), { maxAge: 31557600000 }));
Finally, if you absolutely must include JavaScript in your template like rendering JSON data, etc. using special ejs tag <%- %>
<% if (jsonData) { %>
<script id="jsonData">var jsonData=<%- JSON.stringify(jsonData) %>;</script>
<% } %>

I was able to do that by:
serving the Js folder/file in the node app entry file like so:
app.use(express.static(path.join(__dirname, 'views/js')));
Added DOM functions in a index.js file which is in views/js folder.
Added script tag that links to the index.js file before the end body tag of index.ejs file like so:
<script scr="index.js" type="text/javascript"></script>
Note that the src in the script tag does not have "./js/index.js". I actually don't know why it works that way (same with external css stylesheet).

You can achieve it by adding the code below:
app.use(express.static(path.join(__dirname,public)));
You have to add a directory named public (or whatever you are naming) in your project folder. In that folder you can add your external JS file.
NB: the expression path.join is used to make the directory public available/accessible when you call/initiate app from outside the project folder.

Related

Not found: /products/$lib/assets/images/phone2.svg in sveltekit

So I'm just working with an ecom website with products.
So I created a product list row which will show all of the product and then if the user clicks any of the products it will redirect to the product page which will fetch the specific product information from an api endpoint create in the project (sveltekit) and then I fetch in the +page.ts file of mine and then I export the data as the code below and then I extract the info out. So when I use an image I just put the products.src to it. The products.src looks like this "$lib/assets/images/phone1.svg" but the it log out the error is says
Not found: /products/$lib/assets/images/phone2.svg
I just wanna know where does the /products/ came from when the products.src is "$lib/assets/images/phone1.svg" which I have checked by console it out already
<script>
// Get data
export let data;
const { products } = data;
</script>
<section class="product-page">
<div class="product-image">
<img src={products.src}>
</div>
</section>
I just wanna expect the answer for it plssss.
$lib is an alias for a directory that can only be used statically e.g. in import statements not as part of a dynamic source string.
You can put static asset files in the static directory at the root of the project and reference them directly, e.g. for the file:
/static/images/img.svg
The src path would be
/images/img.svg
Assets that are not in static have to imported or referenced in CSS so they are included in the build. E.g.
<script>
import img from '$lib/images/img.svg';
</script>
<img src={img} />

ejs file loaded but nothing appears

I'm using NodeJS, expressJS and ejs to load files. while rendering index.ejs app.get('/', function(req, res){ res.render('index');, it loaded perfectly but when I'm embedding navbar.ejs in index.ejs <% include(includes/navbar.ejs) %> it is loading fine (no error in console) but nothing is appearing on the page.
Folder managed:
project>app.js ,
project>pages>index.ejs ,
project>pages>includes>navbar.ejs
I believe you have a typo there in your syntax. You're missing the - in the include. It should rather be
<%- include('includes/navbar.ejs'); %>
Also note that the path should be in quotes.

Why am I not able to load a module from within embedded JavaScript?

My objective is to store some data in a module and then be able to retrieve
that data for display using embedded javascript contained in an HTML document. My code for testing this is shown in the following 3 files:
File 1: The HTML (/var/www/html/modTest.html)
<html>
<head>
<title>Module Test</title>
<% var myModule = require("/var/www/cgi-bin/node_modules/modTest") %>
</head>
<body>
<p>Color: <%= myModule.color %>
</body>
</html>
File 2: The Module (/var/www/cgi-bin/node_modules/modTest.js)
var color = "Blue";
module.exports.color = color;
File 3: The CGI Script (/var/www/cgi-bin)
#!/bin/node
var fs = require("fs");
var ejs = require("ejs")
console.log("Content-type: text/html\n");console.log(ejs.render(fs.readFileSync('/var/www/html/modTest.html','utf8')));
When I load the URL of the cgi script into my browser I get a blank page. There is an error message in the httpd error log compaining that "require" is not defined. Can anyone please tell me why this is and (more importantly) how to fix it? Thanks for any input.
... doug
you need require.js or webpack/browserify to link/pack your javascript together for client side and to load your modules with a require - otherwise you would need to include every javascript file in as a
<script src="...">
tag seperately.

Add custom view to jhipster app

I would like to add a custom view to jhipster app on index.html
I already created the link in navbar.html and added the html file on path src/main/webapp/scripts/app/custom/newView.html
<a ui-sref="newView" data-toggle="collapse" data-target=".navbar-collapse.in">
<span class="glyphicon"></span>
<span class="hidden-sm">new view</span>
</a>
When I click on the link it doesn't work. Probably it needs a custom route in angular but I can't figure out how to create it. What else should I do?
In addition to the other answer, here is another piece of information. Maybe somebody else will find it useful. I had a similar problem with a custom view but only in production. Everything was fine in dev mode. In production mode, nothing would display and I had this javascript error that read "could not resolve ... from state ...".
It turns out that my javascript file (where the state was declared) was declared like this in index.html
<!-- build:js({.tmp,src/main/webapp}) scripts/app.js -->
<script src="scripts/app/app.js"></script>
<script src="scripts/app/app.constants.js"></script>
...
<!-- endbuild -->
<!-- custom -->
<script src="scripts/app/pages/quizz/quizz.js"></script>
<script src="scripts/app/pages/quizz/quizz.controller.js"></script>
I had created the separation on purpose, just to make it easier to read. Once I moved it up to have it before endbuild, the problem disappeared. I guess this is related to how the app is packaged somehow? I haven't looked at how it does it.
I've figured it out:
I had to add a angularjs route. Created a js file
src/main/webapp/scripts/app/custom/newv.js with the following content:
angular.module('jCrudApp')
.config(function ($stateProvider) {
$stateProvider
.state('newView', {
parent: 'site',
url: '/newView',
views: {
'content#': {
templateUrl: 'scripts/app/custom/newView.html',
//controller: 'MainController'
}
}
});
});
and import the new script in index.html
<script src="scripts/app/custom/newv.js"></script>

Metalsmith static site pages are missing metadata

I've been attempting a tutorial to set up Metalsmith, and I've gotten to the end of part 1.
I've install node.js and modules. The IDE is Visual Studio 2013 with Node.js tools installed. I've put a basic structure in and I'm trying to get a single page to render with a template.
The instructions tell to put into a file the following:
---
title: Home
template: home.hbt
---
This is your first page
With a template like:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>{{ title }} | Metalsmith Page</title>
</head>
<body>
<div class="main-wrapper">
{{{ contents }}}
</div>
</body>
</html>
The tutorial says that it should render out into a html page but the result I am getting is something like:
--- title: Home template: home.hbt --- This is your first page
When I use the markdown renderer it gives
<p>---
title: Home</p>
<h2 id="template-home-hbt">template: home.hbt</h2>
<p>This is your first page</p>
Debugging the code shows that when it gets to the renderer the YAML front-matter metadata is missing. This seems to be important as the plugins use the metadata to render the page.
The key to the solution lay in the three strange charatcers at the begining of the markdown rendered page

and the YAML front-matter warning:
UTF-8 Character Encoding Warning
If you use UTF-8 encoding, make sure that no BOM header characters exist in your files or very, very bad things will happen to Jekyll. This is especially relevant if you’re running Jekyll on Windows.
Looking at the buffer loaded in Node.js showed the utf8 BOM characters.
One solution would be to make the IDE stop saving it as utf8 with BOM but for me that wasn't a viable option.
I created a workaround as a few small lines that has to be run before any other metalsmith plugin.
var stripBom = require('strip-bom');
var front = require('front-matter');
var extend = require('extend');
// **snip**
.use(function __utf8BOM_workaround(files, metalsmith, done)
{
setImmediate(done);
Object.keys(files).forEach(function (file)
{
var data = files[file];
var parsed = front(stripBom(data.contents.toString()));
data = extend({}, data, parsed.attributes);
data.contents = new Buffer(parsed.body);
files[file] = data;
});
})

Resources