I am working on a blog project for a class using Nodejs, Mongo, and Express. We have been building up to using Express. I had previous JS code to create a slideshow for blog posts. I now need the slideshow to access data from MongoDB and route to a post.ejs file with the matching title (so it can find it on the database and show it on the post.ejs file). I cannot use the slideshow buttons because as I mentioned before that was vanilla js used before being introduced to Node. How can I convert the old vanilla JS to work with express and pull data from Mongo DB? I have managed to learn a lot on my own but I'm stuck now.
Here it my GitHub repository. https://github.com/mmercad4/Marco_800951815/tree/milestone-5
The old JS is in /public/assets/main.js
My post controller is in controllers/postController.js
My jquery folder for ajax is in public/assets/jquery.js
And finally my index.ejs and post.ejs are located in the views folder.
You can modify your vanilla JS files and make them into ejs templates. Use the same syntax that you used for post.ejs so that you can access the data you pass in.
On your server you should set up a route handler such as app.get("/example"). Inside of your route handler, you should query your mongodb instance for the data you need. Now take your newly modified ejs file and render it, passing in the result of the query from mongodb. Here's an example:
app.get("/example", (req, res) => {
const data = getDataFromMongo() // insert your query here
res.render("main", data);
}
If you want your client to be responsible for fetching the data instead, then skip transforming your vanilla files into ejs, and you can simply return the mongodb data as JSON like so:
app.get("/example", (req, res) => {
const data = getDataFromMongo() // insert your query here
res.json(data);
}
Now in your client side code, make an ajax GET request to "/example" and you can use the JSON returned however you wish. No need for ejs template syntax here.
So it's up to you to how you want to control access to your data. The first method handles everything server-side. The second method splits responsibility between server and client. In this case, the server acts as more of a data API than a rendering engine.
Related
I'm unsure of how to apply the MVC architecture to my node web app, in specific separating the model from the controller.
The current structure has the views separated properly (all my .ejs files) and then I guess that my app.js is like the controller as it contains all the routes to respond to http requests. The routes are then handled in a queries.js file which is where I query my database using node-postgres (most of the views rendered are either displaying information from the database or displaying forms so the user can insert data to the database). Should I be doing this differently, or more specifically should I try to create a model that contains raw data from the database and have the route handlers manipulate this data instead of directly querying the database (not sure how I would handle inserting into the database then...)? I'm just concerned that the current way I have structured my web app will make it difficult to manage as it grows and difficult for other to understand and add on to.
Here is an example of how the web app is currently structured: Say a user clicks a button to display all the active orders, my app.js file would look something like this
const db = require('./queries')
app.get('/activeorders', db.getActiveOrders)
My queries.js file would then handle this route like so:
const Pool = require('pg').Pool
const pool = new Pool({
user: process.env.USER,
host: process.env.HOST,
database: process.env.DB,
password: process.env.PASSWORD,
port: process.env.PORT,
})
const getActiveOrders = (request, response) => {
const queryOrders = 'SELECT * FROM orders WHERE complete=0 ORDER BY date_rec DESC;';
pool.query(queryOrders, (error, results) => {
if(error) {
throw error
}
var ordersObj = results.rows;
response.render('pages/activeorders', {
ordersObj: ordersObj
})
})
}
module.exports = {
getActiveOrders,
}
As can be seen in the handler the database is queried and stores the results in an object that is then passed to the activeorders.ejs file when rendered.
Maybe using a middleware allowing you to make an API from a Postgresql database.
Any change made on the databases will be propagated and available to you API. It will also let a lot of modularity to possible filters/ select ...
And for complex queries DBA will be able to develop stored procs available to everyone by API. That is the Model layer. Only SQL exposed through a middleware.
Controller will be how you made you API calls and data transformations if needed to refresh data based in you View
Abstracting the model layer with a middleware definitely a huge economy on time.
For postgres majors options : postgres & pgrest
In MVC pattern we split each part of the application because this approach to software development for complex needs by connecting the implementation to an evolving model
I suggest you visit sample-mvc-express-postgres to understand structure code
If you are interested in design pattern, visit https://dev.to/salah856/implementing-domain-driven-design-part-i-5a72, This link explains how to use DDD in your application and show how to design each layer of the application
Set app.js as root file and create a controller and a model folder. Define all models in model folder, while in controller first import model files handlers and create all APIs or queries function. Then in the root app.js file import controller functions handler and run it.
I am able to connect to my database and see the data in an array using below code
app.get('/goalkeepers', (req, res) => {
Transfer.find({}, (err, found)=>{
if (err) {
console.log(err);
}
else {
res.json(found)
with Transfer being the schema model to connect to collection in database.
When i load the html page i can see array of all saved data from db so thats cool, i know i can access it and its there and working.
But how can i show this data on an actual html page in nice format etc, not just the raw data.
of course I would render a specific page eg. res.render(pagename) where currently you can see res.json(found)
I googled a lot and mostly confusing as a newbie, surely can be a simple way to get this data on to my web pages?
thanks
You have to create a file with ext EJS and send your data to it. You can use CSS to style your data.
Watch this tutorial: https://www.youtube.com/watch?v=p5eCYKiZN-4
I'm new to node js and vue development and I want to create a process where I can create and upload a JSON file to my server when the user saves data in a form. This process should be done in the background. Later I want to read and update that file from the server when the user changed something.
So my first idea was to use fs.writeFile() this doesn't work very well and I think this only works for local stuff is that correct?
var fs = require('fs')
export default {
methods:{
send(){
fs.writeFile("/test.json","Hello World!",function(err){
if(err){
throw err;
}
});
}
}
}
Furthermore it looks like fs.writeFile doens't work with vue because it throws this error:
TypeError: fs.writeFile is not a function at VueComponent
So my second idea was to use express js with the app.post('/api/apps',...) and app.get() method. Here I have no idea how to implement that into the vue framework because I have to call the api like mydomain.com/api/apps but this doesn't work too.
So what is the best way to create, read, upload, delte files into a specific folder on my server? And how it works with vue? I tend to express js.
I'm using vue cli :)
Thanks in advance :)
EDIT
Now what I do is:
I created a new folder in my vue project root and named it "backend". In this folder I created a file named index.js and put this code
app.post('/appjson',(req,res) => {
fs.writeFile("/appjson/myJson.json",req.body,function(err){
//handle error
});
});
on the client side I put this code
axios.post('myDomain.com/appjson', {
JSONdata: myJSONdata,
})
My project looks like:
So when I build I get the dist folder and this I can upload on my server and it works fine. But I can't do the call to my backend? Whats wrong do I call the wrong link? Or how can I access my backend? Is the project struture correct or do I need to add the backend to a specific folder?
Vue is client side, your code is trying to write something to the filesystem of the user thats using your website. what you want to do is send this data to your NodeJS server, this requires using a package like Axios to send data to and from the server without refreshing the page. Axios is pretty straight forward to use, what you need will look similar to the function below.
saveJSON (myJSONData) {
const url = myNodeJSURL/savescene
return axios.post(url, {
JSONdata: myJSONdata,
})
Read some tutorials on ExpressJS, It's a pretty painless framework to use. You'll get the data stored in the body of the HTTP request and then you can use fs.writeFile to save data to the local filesystem of your server. Let me know if you need more help.
EDIT:
Your front end needs to be access a domain or IP address associated with your back end in order to communicate with it. Add the snippet below to your ExpressJS application and then when you run the server any requests to localhost:3000 will be handled by your app. You'll also have to update the URL in your Axios call.
app.listen(3000, function () {
console.log('my server is listening on port 3000!')
})
this setup only works for testing purposes because client and server will have to be on the same machine for localhost to mean the same to both. If you want this project to be public then you need to get your own domain for your site and host the ExpressJS application through there. Google compute makes this pretty easy to do, I'd look into that if I were you.
In my server, I retrieve an object from the database and have it in a variable as follows:
let files = [{"file1": "file1Data"}, {"file2": "file2Data"} ... ];
I want this data to be available in my client side JavaScript.
One way to do this would be to set up an API to call within my JavaScript. My thinking is that this would cause an extra round trip. This is because there is one request to load the initial HTML/JavaScript and then a further request to load the JSON data.
Therefore, it would be faster to send the JavaScript to the client along with the initial request that loaded the page.
How can I send a JSON object directly from the server and have it available in my client side JavaScript?
I would use a templating engine such as EJS or Handlebars.
As an example, using EJS (http://ejs.co/) -
Server side:
// Set EJS as the view engine for Express
app.set('view engine', 'ejs');
// or just create a directory named 'views'
app.set('views', [
path.join(__dirname, 'path/to/views'),
]);
app.get('/index', (req, res)=> {
// 'index' must be in views dir
return res.render('index', {
// Pass in foo as the second argument
// to res.render()
foo: 'bar'
});
})
index.ejs (EJS template):
<script>
const foo = <%- JSON.stringify(foo) %>;
</script>
Before serving the static files, you would need to fetch the object from the database and add the content to the files you're sending. So some kind of server-side processing. The Node app could read index.html from disk, parse it, find a place where to set the json data, and then send the data as response.
I would not do it that way though. You're already making multiple requests, e.g., client asks for index.html. Server sends that file. Client then asks for all the resources like css, JavaScript, images, fonts, etc. Another little request for some json data won't hurt.
As you said, API is the most common method if you retrieve the data from database (since you might do it after the website is loaded). If you retrieve the site when the user is requesting website, my method will be simply render it into the HTML that you serve to user.
I'm gonna show a simple sample here with pure app.write and app.get.
app.get('/', (req, res)=> {
res.write("<h1>Hi</h1>");
res.write("<script>var data="+ObjectYouRetrieve+";</script>");
res.end();
})
I have a node app to display webviews for facebook messenger, using ejs templates and express.
1.) How to pass data from node to the "frontend"/client?
-until now I am doing that using res.render('index', {key: value});
is there another way?
2.) How to pass data from the client to the backend.
-I used /post when i had a form but what if i dont have a form, as an example i will get the facebook id of the user in a async way on the frontend and want to transmit it to the backend.
I have recently been using a p5.js library. It has a method called loadJSON() to get data from the backend node app. And for post i just use httpPost() method, I invoke it in the function once a button was clicked e.g.
It's a nice library tough suggesting you using the minified version.