Pass server-side data into Angular - javascript

i'm currently trying to display the name of the logged-in user in my MEAN app. I'm using the EJS templating engine and I'm able to get the username showing by putting <%- user.username %> in my markup. The problem with this is that I don't really want to my mixing angular and embedded scripts in the same files, I'd like to pass the server-side data into Angular. I've tried ng-init but I'm not having any success at all with it.

I will assume you are using ExpressJS 4 it will be a little different in version 3, however the approach will be the same for both versions:
Node/Sever side
var express = require('express');
var bodyParser = require('body-parser');
var schema = require("./schemas");
var app = express();
var router = express.Router();
router.get('api/account', function(req, res){
res.json({ "login": req.session.user.login }); /*access the session account not sure if this matches your login location you will adapt it to your own*/
});
Angular/Client Side
You then invoke from your controller or service the url api/account with a GET request to receive the JSON like:
$http.get("/api/account").then(function(data){ console.log(data); });
then you could do something like:
$scope.login = data.login;
and in the html
{{login}}

From what I understand of Angular, it discourages server-side setting of templated values in HTML code. Consider setting up a JSON service that provides the data, and fetching the data over JSON. There is an example at the end of the Angular Tutorial that may make this clearer.

I do the exact same thing and mix EJS to embed things like my server info (to initiate a socket connection from the client). If you wanted to keep this purely client-side, you would need to have AngularJS fetch the server-side data using a service / factory - and then affect any views you have depending on said data.
ng-init only applies to things which live inside the "Angular" scope.

Related

convert vanilla JS to work with Nodejs, Mongo, and Express

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.

setting up a lot of routes in node.js

I've created a webpage to use it locally as a way to save information about random topics and college stuff. I have a ton of routes like the ones shown below:
//app.js - using node and express
app.get('/page1', function(req, res){
res.render('page1');
});
app.get('/page2', function(req, res){
res.sendFile('views/page2.html', { root: __dirname });
});
Each one of these routes has a .ejs file or a .html file, and they are all quite small.
I don't think I've made any major mistakes, but I gotta a feeling I'm not using "best practices", or at least could be doing some differently.
Is there anything wrong with using a lot a routes like this? Should change something to optimize the rendering of my pages?
As I said before, I'm using .ejs on most of the pages, and most of them have the same header.ejs and footer.ejs. Every time I change pages that have the same header/footer, do they get loaded again, or since they are using the same header/footer files the server only requests the content in between?
what's the difference between using res.render and res.send?
Should I be using a different syntax: const express = require('express'); & const app = express(); instead of var express = require('express'); & var app = express();
``` or this
app.get('/page1', (req, res) => {
res.render('page1');
});
```
Instead of the first block of code above.
Thanks! :D
Is there anything wrong with using a lot a routes like this? Should change something to optimize the rendering of my pages?
Nothing technically wrong with it. Many plain res.sendFile() routes can probably be replaced with a single express.static() middleware statement to simplify your code.
Lots of res.render() routes that don't pass any customized data to EJS can also probably be replaced by a single middleware that handles either a whole directory of template files (and their corresponding routes) or a list of files. That would be a lot more DRY than spelling out each route separately.
As I said before, I'm using .ejs on most of the pages, and most of them have the same header.ejs and footer.ejs. Every time I change pages that have the same header/footer, do they get loaded again, or since they are using the same header/footer files the server only requests the content in between?
EJS caches templates in memory (unless you disable caching) so the header and footer templates won't get loaded over and over again from disk.
what's the difference between using res.render and res.send?
These are fully covered in the documentation. In a nutshell, res.render() supports your template engine and local data to feed to the template engine to allow it to add data to the template. res.send() just sends the raw content you give it.
Should I be using a different syntax: const express = require('express'); & const app = express(); instead of var express = require('express'); & var app = express();
It is considered a good practice to use const whenever the variable you are declaring should get its initial value and not be assigned to again. In addition to some coding safety, this also can sometimes allow the interpreter to do more optimizations when using the variable (since its value can't be changed).

In Node.js/Express.js, how can I transfer a JSON object from server to client?

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();
})

Node.js get value from end of url

Is there a way for me to create a URL like this: http://localhost/example/143 and use 143 as an id to fetch content? I do not want question marks or other things like this. An example website like this is imgur which doesn't use question marks.
I have looked for other options, but all of their questions requires ?=somequery in order for it to work.
Thanks
Use express.js named route parameters: http://expressjs.com/en/guide/routing.html#route-parameters
Use req.params as in express documentation
Route path: /users/:userId/books/:bookId
Request URL: http://localhost:3000/users/34/books/8989
req.params: { "userId": "34", "bookId": "8989" }
In case of using raw http
for using with raw http module you can use str.split("/")[2];
var http = require('http');
function handleRequest(request, response){
response.end('It Works!! Path Hit: ' + request.url);
var str = request.url;
var exampleId = str.split("/")[2];
}
var server = http.createServer(handleRequest);
server.listen(8080, function(){});
What you are describing is what's referred to as a restful web api implemented with routing You'll typically want to build your site in a MVC (Model View Controller) framework to get this functionality. Express.js is new hotness on the block - especially in the context of javascript and node.js categories tied to this question - but there are others out there as well. Ruby on Rails made MVC and restful routing popular, and MS has ASP.NET MVC. PHP even has CodeIgniter and others I'm sure, and Angular2 is Google's MVC baby at the moment.
The point is, there are many frameworks to choose from that will give you the restful URL routing you're looking for. Find one you like, and run with it!

Node.js Express: Passing data from URL and session into served JavaScript file

I've been building a web-socket application in which the client opens a link to a game instance, and then the server attempts to connect the client to the respective Socket.io room on which the game will transmit information. For example, connecting to '/game/abc' would load up the game page and connect the socket on the page to the 'abc' room on the server.
The problem with this is getting the client JavaScript file to emit the game ID and the username of the user connecting. I want it to act in the following way:
Client.js
var socket = io();
socket.emit("newUser", username, gameID);
I have managed to accomplish this by passing both my client.html and client.js page through an Express template renderer:
Server.js
app.get(/^\/game\/([a-zA-Z0-9]*)$/, function(req, res){
var game = req.params[0];
var user = req.session.name; //gets username stored in session
res.render("client.html", {username: user, gameName: game});
});
app.get(/game\/(.*)\/client.js/, function(req,res){
res.render("client.js", {username: req.session.name, gameName: req.params[0]});
});
The second app.get() allows for the gameName to be passed along to client.js through client.html in the form of a parameter in the url.
Client.html
<script src="{{gameName}}/client.js"></script>
Finally after two passes, the game ID and username both are put into client.js by the template engine.
Client.js
var socket = io();
socket.emit("newUser", "{{username}}", "{{gameName}}");
//leads to socket.emit("newUser", "user", "abc"); when passed through renderer
Although this gets the job done, it feels incredibly convoluted and indirect. I've looked up alternatives to this, with the answer at node.js express rendering inside included js files recommending to use AJAX calls. However, I have not been able to figure out how to exactly configure such an AJAX call. Is there a more effective way to overcome this problem?
You can simplify all of this and avoid rendering the templates in Express to pass that variable in this case.
You already have the gave name available to your client-side code in the window.location object. You can either parse it manually with a simple regex (in this case) or you can use something that is called a client-side router which there are a lot to choose from.
There is one simple client-side router inspired by Express.js: Page.js, which would allow you to use a very similar code that you use right now in Express.
Many client-side frameworks have routers build in.

Categories