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

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} />

Related

Set up Pendo in Next.js

We're using Next.js 12 with SSR in our project. I've read through the Pendo documentation but I'm still not sure where to place the install snippet in our code, as Next.js doesn't provide an index.html file. We're using layouts however, is the top of the layout a good place to place Pendo?
I was trying to put the snippet as a function inside of the layout component's return, but it apparently doesn't work like this.
Thanks for any help!
Your _app.tsx should start with something like this and this will work:
function MyApp({ Component, pageProps }: AppProps) {
return (
<>
{/* Pendo Offsite MPA setup code snippet */}
<script
dangerouslySetInnerHTML={{
__html: `
(function(apiKey){
...
...
});
});`,
}}
/>
<sometag />
</>
);
}
Paste your Pendo script code as is into the placeholder above as a comment block.
The _app.js file works as index.js, the entry point for the whole application including every sub-page of it.

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

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.

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>

How to display progress of the file upload using node.js in real time

I am working on the project which simply read the txt/csv files from the directory and store in the database.
The upload function works like a charm but the problem is that I want to display the progress - any notification that tells the users that the system is working on the files.
Here is my HTML markup
<div class="form">
<input type="file" id="uploadFile" />
<button id="submit" type="button">Upload</button>
</div>
<div class="terminal">
<! -------------------RESULT---------------------->
</div>
I have the div called terminal to display the progress of file uploading. The way I place text inside the div is to use the innerHTML function of javascript. Thus, my upload code is as follows
var files = fs.readdirSync(folder_path);
// Loop through files gathered from folder reading
for(i=0; i<files.length; i++) {
document.getElementbyId("terminal").innerHTML+=files[i]+"<br/>";
var fileData = fs.readfileSync(folder_path+'\'+files[i], 'utf8');
// Upload function below
}
The above markup is a part of my js file which serves as an uploader. I first read the folder with fs.readdirSync, then iterate through the array of files gathered from readdirSync function. I want to display the file name in each loop in real time.
But it just displays everything once the upload has finished. So I don't know how to make it display the progress in real time or in other word, just like the console which displays any information in real time.
You don't have to loop, you can easily port this to your frontend app:
Monitoring XHR Progress
https://developer.mozilla.org/en/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Monitoring_progress

sails.js use different layout with different js libraries

I'm creating my first nodejs/sails.js project, I want to use 3 different layout for 3 different occasions:
frontend_layout.ejs
admin_layout.ejs
mobile_layout.ejs
In frontend_layout.ejs, I want to load bootstrap.css, jquery.js and
bootstrap.js.
In admin_layout.ejs, I want to load bootstrap.css, angular.js and
ui-bootstrap-tpls.js(angular-ui js library).
In mobile_layout.ejs, I want to load ionic.css and ionic.bundle.js
I have created 3 folders in sailsProject/views/ which are admin_pages, mobile_pages and frontend_pages, the 3 layout.ejs files reside in each of these folders respectively, but no matter which layout I load, it always include all the css/js files in assets/js and assets/styles. I know I need to do something to pipeline.js, but how exactly? I'm not efficient at grunt, so I would really appreciate if anyone could point me which config files need to be modified and how... Thanks!
I wanted something very similar in my project, except I also wanted to take advantage of Sail's cool built-in ability to auto minimize/uglify javascript files for "sails lift --prod" in various layouts with different sets of javascript files. This answer only deals with the JS files, but you can make similar changes to support the same concept with your CSS files.
In my project I had 2 different layouts -- layout.ejs and layoutadmin.ejs. I created a new /assets/jsadmin folder which holds my admin javascript files. I left the sails existing /assets/js folder as-is to hold the javascript files for the public web pages.
My goal was for the /assets/js folder contents to be inserted between these tags (sails does this by default and these tags are used in the layout.ejs file):
<!--SCRIPTS-->
<!--SCRIPTS END-->
While the /assets/jsadmin folder contents was to be inserted between these tags (I made up these "custom" tag names and they are used in the layoutadmin.ejs file. I will add add support for this new tag in the rest of this answer):
<!--SCRIPTS_ADMIN-->
<!--SCRIPTS_ADMIN END-->
I created a full code sample demo of this here.
For development...
(sails lift), I modified so sails would populate my custom tags with the assets/jsadmin js files upon lifting.
I modified tasks/pipeline.js by adding a new variable called jsAdminFilesToInject which is very similar to the existing jsFilesToInject except it collects the js files from the jsAdmin folder.
var jsAdminFilesToInject = [
// Load sails.io before everything else
//'jsAdmin/dependencies/sails.io.js',
// Dependencies like jQuery, or Angular are brought in here
'jsAdmin/dependencies/**/*.js',
// All of the rest of your client-side js files
// will be injected here in no particular order.
'jsAdmin/**/*.js'
];
Note: I also had to export this new variable at the bottom of the pipeline.js file.
module.exports.jsAdminFilesToInject = jsAdminFilesToInject.map(function(path) {
return '.tmp/public/' + path;
});
I modified tasks/config/sails-linker.js by adding a new devJsAdmin task where it looks for tags and calls the new .jsAdminFilesToInject added in the pipeline.js file above.
devJsAdmin: {
options: {
startTag: '<!--SCRIPTS_ADMIN-->',
endTag: '<!--SCRIPTS_ADMIN END-->',
fileTmpl: '<script src="%s"></script>',
appRoot: '.tmp/public'
},
files: {
'.tmp/public/**/*.html': require('../pipeline').jsAdminFilesToInject,
'views/**/*.html': require('../pipeline').jsAdminFilesToInject,
'views/**/*.ejs': require('../pipeline').jsAdminFilesToInject
}
},
I Added a new task step to the tasks/register/linkAssets.js file which calls the devJsAdmin added above.
'sails-linker:devJsAdmin',
To test, run sails in demo mode:
sails lift
Browse to http://localhost:1337/home - you will see it is using the layout.ejs template and viewing the source will show the following at the bottom (files pulled from js folder):
<!--SCRIPTS-->
<script src="/js/dependencies/sails.io.js"></script>
<script src="/js/jquery-1.10.2.js"></script>
<!--SCRIPTS END-->
Browse to http://localhost:1337/admin - you will see it is using the layoutadmin.ejs template and viewing the source will show the following at the bottom of the source (files pulled from jsAdmin folder):
<!--SCRIPTS_ADMIN-->
<script src="/jsAdmin/dependencies/jquery-1.10.2.js"></script>
<script src="/jsAdmin/knockout-3.3.0.debug.js"></script>
<!--SCRIPTS_ADMIN END-->
For production...
(sails lift --prod), I wanted to do the same as development except I first wanted to concat and uglify the production javascript that goes in my new SCRIPTS_ADMIN tags.
I added a new jsAdmin section in the grunt tasks/config/concat.js file which pulls in the files from the previously added jsAdminFilesToInject in the pipeline.js to produce a concat/productionAdmin.js output file.
jsAdmin: {
src: require('../pipeline').jsAdminFilesToInject,
dest: '.tmp/public/concat/productionAdmin.js'
},
I added a new distAdmin section in the grunt tasks/config/uglify.js file which makes the concat/productionAdmin.js "ugly" by producing a new min/productionAdmin.min.js file.
distAdmin: {
src: ['.tmp/public/concat/productionAdmin.js'],
dest: '.tmp/public/min/productionAdmin.min.js'
}
I added a new prodJSAdmin section in the tasks/config/sails-linker.js file which adds the min/productionAdmin.min.js file between the SCRIPTS_ADMIN tags.
prodJsAdmin: {
options: {
startTag: '<!--SCRIPTS_ADMIN-->',
endTag: '<!--SCRIPTS_ADMIN END-->',
fileTmpl: '<script src="%s"></script>',
appRoot: '.tmp/public'
},
files: {
'.tmp/public/**/*.html': ['.tmp/public/min/productionAdmin.min.js'],
'views/**/*.html': ['.tmp/public/min/productionAdmin.min.js'],
'views/**/*.ejs': ['.tmp/public/min/productionAdmin.min.js']
}
},
Finally, I called this new prodJSAdmin from the prod grunt task by adding a line in the prod.js file.
'sails-linker:prodJsAdmin',
Run sails in production mode:
sails lift --prod
Browse to http://localhost:1337/home - you will see it is using the layout template and viewing the source will show the following at the bottom (using production.min.js):
<!--SCRIPTS-->
<script src="/min/production.min.js"></script>
<!--SCRIPTS END-->
Browse to http://localhost:1337/admin - you will see it is using the layoutadmin.ejs template and viewing the source will show the following at the bottom of the source (using productionAdmin.min.js):
<!--SCRIPTS_ADMIN-->
<script src="/min/productionAdmin.min.js"></script>
<!--SCRIPTS_ADMIN END-->
By default, Sails automatically insert all your css files (assets/styles) into tags between STYLES and STYLES END and js files (assets/js) into tags between SCRIPTS and SCRIPTS END.
<!--STYLES-->
<!--STYLES END-->
.
.
.
<!--SCRIPTS-->
<!--SCRIPTS END-->
This is set in pipeline.js file. By default it has set to get all css files from assets/styles. You can find it in cssFilesToInject section.
'styles/**/*.css'
You can change it as you wish. you can comment or delete it simply. (keep in mind if you want to put some css files common to every layout you can put them in here.)
Same for the js files. By default it has set to get all js files from assets/js. You can find it in jsFilesToInject section. Remove or add js files according to your requirement. You can find more information about grunt globbing patterns in here which helps to understand filtering pattern.
So easiest thing you can do now is put your layout specific files out side those tags(STYLES and SCRIPTS)
For example look following code sample,
<!--STYLES-->
<!--STYLES END-->
<!--STYLES SPECIFIC TO THIS LAYOUT-->
<link rel="stylesheet" href="/styles/some_layout_specific.css">

Resources