I'm doing a products page using express with pug as a template and storing the data in a JSON file, but on the products page the images are not loading, I just receive the links back.
let me know if you need me to show you something else, I also have a route.js file.
JSON
[
{
"name": "Jetpack pitus",
"price": 150000,
"model": "2021",
"img_url": "https://cdn2.unrealengine.com/Fortnite%2Fpatch-notes%2Fv4-2-contentupdate%2Fheader-v4-2-content-update%2FJetpack-1920x1080-20e524ca933c434a4c07719a5405e60041b47a1f.png"
},
{
"name": "Jetpack venus",
"price": 125000,
"model": "2020",
"img_url": "https://www.ginx.tv/uploads/Iron_Man_Stark_industries.png"
},
{
"name": "Jetpack enormus",
"price": 200000,
"model": "2022",
"img_url": "https://www.x-jetpacks.com/wp-content/uploads/Jetpack-NX-Square-front-and-back.jpg"
}
]
pug:
extends layout
block content
each product in data
p=product.name
p=product.price
p=product.model
p=product.img_url
p
a.btnOrder(href='/orders') Make an order!!!
index.js:
const express = require('express');
const pug = require('pug');
const path = require('path');
const routes = require('./routes/routes');
const app = express();
app.set('view engine', 'pug');
app.set('views', __dirname + '/views');
app.use(express.static(path.join(__dirname, '/public')));
const urlendcodedParser = express.urlencoded({
extended: false
});
app.get('/', routes.index);
app.get('/products', routes.productsData);
app.get('/orders', routes.orders);
app.get('/submitted', routes.submitted);
// app.post('/submitted', urlendcodedParser, routes.submitted);
app.listen(3000);
Assuming you are invoking the render method correctly and passing in your array as data, then to show images it should be something like:
each product in data
p=product.name
p=product.price
p=product.model
p
img(src=product.img_url)
p
a.btnOrder(href='/orders') Make an order!!!
You might also want to make the order request more specific rather than a common page for all products:
a.btnOrder(href="/orders?model="+product.model) Make an order!!!
Of course you have to code the route /orders to read the query string.
Related
We have blog in a NuxtJs project deployed using docker and traefik's PathPrefix('/blog') so instead of being served from https://example.com/ is served from
https://example.com/blog/
version: "3.9"
services:
{{ project_id }}-awesome-blog-{{ awesome_blog_env }}:
# etc..
labels:
- traefik.http.routers.awesome_blog-{{ awesome_blog_env }}-router.rule=Host(`{{ awesome_blog_host_dns }}`) && PathPrefix(`/blog`)
# etc..
- {{ docker_network }}
networks:
{{ docker_network }}:
external: true
The issue is that because of the PathPrefix Nuxt does not seem to know the actual page. As it's receiving /blog/ as path it doesn't match any expected route
this is what this.$router prints out in the server on the server from https://example.com/blog/
{
"name": null,
"meta": {},
"path": "/blog/",
"hash": "",
"query": {},
"params": {},
"fullPath": "/blog/",
"matched": []
}
And this is what it prints in local from http://localhost.com:3000/
{
"name": "index___en",
"meta": {},
"path": "/",
"hash": "",
"query": {},
"params": {},
"fullPath": "/",
"matched": [{
//...etc
name: "index___en",
// ..etc
}]
}
I tried using the
router: {
base: '/blog/
}
Which in local works but in the server seems not to work (doesn't even get to the nuxt site and printing the server 404)
As an "ugly" alternative I tried copying all the pages inside the /blog/ folder and they do respond but my serverMiddleware does not (returns 404)
this serverMiddleware is setup like this:
nuxt.config.js
serverMiddleware: ['~/server-middleware/index.js'],
server-middleware/index.js
const nocache = require('nocache');
const express = require('express')
const buildRouter = require('../server/router.js')
const app = express()
app.use(express.json())
app.use(nocache());
buildRouter(app)
module.exports = app
server/router.js
module.exports = function (app) {
const buildApiRoute = require('./controllers/api')
buildApiRoute(app, '/api')
}
Tried with /blog/api, too
module.exports = function (app) {
const buildApiRoute = require('./controllers/api')
buildApiRoute(app, '/blog/api')
}
Anyways, is there any way to tell nuxt to ignore the /blog/ slug of the url o something similar?
Magic code
// Before anything
this.$router.fullPath = this.$router.fullpath.replace('/blog', '/')
this.$router.path = this.$router.path.replace('/blog', '/')
I created 4 serverless routes
/api/list (GET)
/api/add (POST)
/api/update/:id (PUT)
/api/remove/:id (DELETE)
I included them in the api/now.json file like this:
{"src": "/api/list", "dest": "./list.js", "methods": ["GET"]},
{"src": "/api/add", "dest": "./add.js", "methods": ["POST"]},
{"src": "/api/update/*", "dest": "./update.js", "methods": ["PUT"]},
{"src": "/api/remove/*", "dest": "./remove.js", "methods": ["DELETE"]}
The /api/list and /api/add routes which don't use parameters are working, but /api/update and /api/remove aren't working, because I probably didn't use the regex on the api path in the above quoted now.json file correctly.
The handler for the router looks like this (only the relevant path)
app.put('/api/update/:id', (req, res) => {
...
});
module.exports = app;
The src is the incoming request path that you want to match, and dest is the file that should execute.
That means you don't need any routes for your first two because visiting /api/list will execute the function in your file /api/list.js and /api/add will execute /api/add.js.
You can use rewrites in a now.json file to define routes similar to express patterns:
{
"rewrites": [
{ "source": "/update/:id", "destination": "/api/update" },
{ "source": "/remove/:id", "destination": "/api/remove" }
]
}
An example function in /api/remove.js would look like:
module.exports = (req, res) => {
const { id } = req.query;
res.send('Removing ID ' + id);
});
Alternatively, you could name your file /api/remove/[id].js and then you wouldn't need to define rewrites configuration at all. This is called Path Segments.
I am trying to use AJAX to get the JSON data from an API to display on my EJS file in Node JS. However, it seems that nothing is being pulled from the API in the first place. How can I display data from an API to page in Node JS? I have been trying for hours to find a solution to this one. Here is what I've got so far.
**index.js**
var express = require('express');
var app = express();
var url = require('url');
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/public'));
// views is directory for all template files
app.set('views', __dirname + '/views');
app.use(express.static(__dirname + '/public'));
app.set('view engine', 'ejs');
app.get('/', function(request, response) {
response.render('pages/index')
});
app.listen(app.get('port'), function() {
console.log('Node app is running on port', app.get('port'));
});
var http = require("http");
(function($) {
$(function() {
var status = $('#status');
getData();
function getData() {
// Get the data from the Walmart API
$.ajax({
url: "http://api.walmartlabs.com/v1/trends?format=json&apiKey=
{api_key}",
dataType: "jsonp",
success: function(data) {
//Show this data in the console
console.log(data);
//variable instantiation
var itemId = data['items']['itemId'];
var name = data['items']['name'];
var regularPrice = data['items']['msrp'];
var salePrice = data['items']['salePrice'];
//Place data in HTML
$("#productId").html(itemId);
$("#name").html(name);
$("#regularPrice").html(regularPrice);
$("#salePrice").html(salePrice);
}
});
}
**index.ejs**
<!DOCTYPE html>
<html>
<head>
<title>Store App</title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js">
</script>
<script type="application/json" src="/js/index.js"></script>
</head>
<body>
<h1>Store App</h1>
<p>Welcome to the Store Node site. Here, you will find hot products on the
Walmart website. You can also browse by category or search by product id or
name.</p>
<section class="item-container">
<h1 id="name"></h1>
<ul id="current_trends">
<li id="productId"></li>
<li id="regularPrice"></li>
<li id="salePrice"></li>
</ul>
</section>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js">
</script>
</body>
</html>
**package.json**
{
"name": "node-walmart",
"version": "1.0.0",
"description": "walmart web services",
"main": "index.js",
"dependencies": {
"express": "^4.16.3",
"ejs": "*"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/sample/node-sample.git"
},
"author": "sample",
"license": "MIT",
"bugs": {
"url": "https://github.com/sample/node-sample/issues"
},
"homepage": "https://github.com/sample/node-sample#readme"
}
Use EJS like this Node-Cheat
and then you can do it like:
app.get('/', function(req, res, next) {
//see message is passed to index.ejs and ejs will take care of rendering it
//so same way you can load your api data here like:
axios.get('http://api.walmartlabs.com/v1/trends?format=json&apiKey={api_key}')
.then(function (apiData) {
//now pass apiData to index.ejs to take care of it
res.render('index',{message:"Hello World!", apiData: apiData});
})
.catch(function (error) {
//render your error.ejs here
});
});
See axios docs here.
In case you want to use new syntax:
app.get('/', async (req, res, next) => {
//see message is passed to index.ejs and ejs will take care of rendering it
//so same way you can load your api data here like:
try {
const apiData = axios.get('http://api.walmartlabs.com/v1/trends?format=json&apiKey={api_key}');
//now pass apiData to index.ejs to take care of it
res.render('index',{message:"Hello World!", apiData: apiData});
}
catch (e){
//render your error.ejs here
}
});
It's don't work like that. You need to make the call in your API to render it on a page. IIFE don't work here as you used.
Project repo
After installed lokijs I created the following database.js file:
var loki = require('lokijs');
var db = new loki('db.json');
db.addCollection('top').insert([
{ term: 'JavaScript' , style : 'warning' },
{ term: 'Angular 2' , style : 'danger' },
{ term: 'NodeJS' , style : 'success' },
{ term: 'REST' , style : 'primary' }
]);
db.addCollection('searches');
db.saveDatabase();
As soon as I added require('./database.js'); in my server.js file, nodemon is caught in a restart loop. nodemon main
var express = require('express');
var app = express();
app.set('view engine', 'ejs');
app.set('views', __dirname + '../public/views');
app.use(express.static(__dirname + '/../public'));
require('./database.js');
require('./routes.js')(app);
module.exports = app;
You can add all the json files of lokijs in ignore array of nodemon.json like below
{
"ignore": [
"db1.json",
"db2.json"
]
}
Now nodemon will not restart when you use saveDatabase function of lokijs
Ah just realized I needed to ignore the db.json file, since that keeps getting overwritten.
nodemon main.js --ignore db.json
This will prevent the server restart loop.
After looking at the examples and answers given in related questions here on StackExchange and trying to use them to resolve my issue, I'm finally posting my question. Grrr....
So My goal is to eventually access some complex json via api and REST. I was hoping to import (currently via require but eventually via Oauth'd RESTful API) json, parse it to discover the key/value pairs (including nested keys and values) and then at the very least create an object I could then display and have access to all elements. I hope that's making sense. Anyway, to begin to build that I thought I'd get some example json and require it. Well I initally tried some json from the API that I'm going to use but I'm afraid that it was causing issues (well, my inexperience with node, express and jade is really the cause) so I decided to simplify and grab some very simple json. A colorsArray. So .. now some code. Here's the console output including the error I get after error I get after attempting to render the web page. Please ignore the pathings because I'm using my php oriented Eclipse IDE to run nodeclipse (which is working awesome btw)
{ colorsArray:
[ { colorName: 'red', hexValue: '#f00' },
{ colorName: 'green', hexValue: '#0f0' },
{ colorName: 'blue', hexValue: '#00f' },
{ colorName: 'cyan', hexValue: '#0ff' },
{ colorName: 'magenta', hexValue: '#f0f' },
{ colorName: 'yellow', hexValue: '#ff0' },
{ colorName: 'black', hexValue: '#000' } ] }
Express server listening on port 3000
After some work (with advise from comments and answers below) I'm now getting the following in my browser
**Express**
Welcome to Express
[object Object]
I've update code in the sections below to reflect advice.
Here's my current app.js
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, user = require('./routes/user')
, http = require('http')
, path = require('path');
//Load projects as JSON.
var ob = require('./simple.json');
console.log(ob);
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// set object for templates
app.locals('ob' , ob);
// development only
if ('development' === app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', routes.index);
app.get('/users', user.list);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
and current index.js
/*
* GET home page.
*/
exports.index = function(req, res){
res.render('index', { title: 'Express' , ob: req.body});
};
index.jade
extends layout
block content
h1= title
p Welcome to #{title}
p #{ob}
for(var prop in ob)
p #{ob.colorName}: #{ob.hexValue}
and finally layout.jade
doctype html
html
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
body
block content
ADD-->Initially forgot to add the json file I'm trying to import
{
"colorsArray":[{
"colorName":"red",
"hexValue":"#f00"
},
{
"colorName":"green",
"hexValue":"#0f0"
},
{
"colorName":"blue",
"hexValue":"#00f"
},
{
"colorName":"cyan",
"hexValue":"#0ff"
},
{
"colorName":"magenta",
"hexValue":"#f0f"
},
{
"colorName":"yellow",
"hexValue":"#ff0"
},
{
"colorName":"black",
"hexValue":"#000"
}
]
}
So there you have it. Again, I'd LOVE to be able to get the json, parse it to identify the elements (including nested sub-elements) and have it as an object I can access for logic and display. But right now, I'd be giddy with being able to just display it in the jade and access the object's elements via a loop.
Thanks for taking time to look through this and I know this has been answered here in other examples but I've spent a week trying to employ those solutions with no luck
When node.js requires a json file it automatically parses it.
You are attempting to parse it a second time here:
exports.index = function(req, res){
var ob = JSON.parse(ob);
res.render('index', { title: 'Express' , ob: ob});
};
Try omitting JSON.parse and pass the object straight to the render method.