View templates and routes in node.js with AngularJS - node.js

Trying to understand how to implement AngularJS in a node.js express app. After setting up express, I need 2 things: routing and a template engine, so normally I would need to do as follows to set the app to use Jade templating engine:
app.register('.html', require('jade'));
...and then I would set routes probably like this:
app.get('/', function(req, res) {
res.render('index', function(err, html){
// ...
});
});
But if I want to use AngularJS for templating, do I still need Jade? And I read about how in AngularJS routes must be configured, does this mean the above way of declaring routes with app.get() would no longer be needed when using AngularJS?

If you don't need to add anything extra to your Angular layout prior to rendering the page for the client (i.e. in some cases you could add a window.user object in the Jade template for authentication when using PassportJS), you can completely ditch Jade altogether and let the Express static middleware render your index.html:
app.use(express.static(path.join(__dirname, 'public')));
Obviously, the files in public/ are all your Angular files, including the index.html. Be sure to require the path module too for path normalization, this isn't required though.
Afterwards, Angular will take care of the rest. This means that all your routes are defined inside the Angular app, and not in the Express routes.

Related

Angular in a NodeJs Server

I'm beginner in Angular. I have a nodejs server and I have Angular for the front end. Now I would like to know if it's possible to have just one server for both ?
Because in some videos from youtube, they had one server for node and one server for angular.
Thank you, bye
At a basic level you'd need to set the static path for your built, static Angular files and if you are using Angular routing you'd probably want to direct all requests to your index.html of the Angular project so that Angular can handle all client side routing.
For example, setting the static path for a built Angular CLI project that sits in the default public folder created by express-generator. The example uses dist as that is the default destination of the Angular CLI project when you execute ng build.
app.use(express.static(path.join(__dirname, 'public', 'dist')));
Catch-all route to direct any requests not caught by your Express application route definitions, such as RESTful routes returning JSON data or similar, to the Angular project's index.html:
// some routes
var users = require('./routes/users');
app.use('/users', users);
// other routes
var todos = require('./routes/todos');
app.use('/todos', todos);
// catch-all route
// needs to go AFTER all other express server route definitions
app.use('*', (req, res) => res.sendFile(path.join(__dirname, 'public', 'dist', 'index.html')));
If using Angular CLI, during development you can run the projects separately, using a proxy.
Hopefully that helps!
Yes, it's possible to have one server for both.
You can serve your AngularJS files via your favourite HTTP server (e.g. express) on your NodeJS server as static files like so:
app.use(express.static(path.join(__dirname, 'client')))
Where client is the directory containing your front-end content.

Is there any (simple) way to pass variable from Express to Vue.js?

Ok, so I'm just starting to learn Vue.js, and man, it's so hard to do things that are very simple when just using EJS for example. I'm close to abandon Vue for my current project, since I just don't know how to pass res.locals.something from Express server to Vue frontend. By the way, it's Passport.js thing - when authenticated, user should be redirected, but I have to pass the info whether user has logged in or not to Vue (res.locals.isLogged = req.isAuthenticated();), and that seems impossible with my current (close to 0) Vue.js skills... The only solution I found was using ajax (axios was my choice) request on the client side, targeting /login/facebook route on the server, and then I could pass the response from Express to Vue, but it cannot work because of the damned CORS issue. So, I cannot use ajax to retrieve the data from Express, and Express and Vue are not natively connected like Express and EJS or Pug for example.
In short - does anyone know of a simple way to pass Express variable to Vue, not including Vue SSR, Express-vue module etc.?
P.S. I'm not using Webpack or anything similar (so, no .vue files etc.) - just a simple index.html file with Vue loaded from CDN.
Ok, one thing that crossed my mind as dirty workaround was using .ejs instead of .html extension, so I could pass the variable to ejs, but I thought it won't work. What I did was just renaming my index.html to index.ejs, passing res.locals.isLogged to ejs template and both Vue and ejs rendered parts of the app are working together, somehow...
So, this is the dirty (sort of) solution...
The question has already been answered but I'm not familiar with .ejs and couldn't follow the solution. For those like me, what I did was :
Sent the data using res.locals or res.render('file.pug', data)
Set the data received as a html data attribute to a tag ( ex : p(id="myParagraph" data-myData= data)
Set the state of the Vuex store using
mounted : function () {
this.$store.state.myData = document.getElementById("myParagraph").getAttribute("data-myData");
}
The same can be used to set the data property of the vue root instance.
From here on you can use the data whenever needed and still retain reactivity.
You're on the right track using res.locals. To get access to the variable in the JS that's in the view, you have to wrap the value in a string: console.log('#{isLogged}'). See example below
app.js
const express = require('express')
const app = express()
app.set('view engine', 'pug')
app.use((req, res, next) => {
res.locals.isLogged = false
next()
})
app.get('/', (req, res) => {
res.render('index')
})
app.listen(3000, () => {
console.log('listening on 3000')
})
views/index.pug
doctype html
html
head
title= title
body
h1= text
script.
console.log('#{isLogged}') // false

Node React structure without view engine

I'm new to node. I was using express-handlebars as my view-engine, but now I've added React and I understood that I no longer require handlebars. The problem that I'm having is that in order to get to the index.html page, without handlebars, I had to use
app.use(express.static('./public'));
Everything gets rendered from react, but what if I want to do some other things when the user goes to the index page like
app.get("/",function(req,res){
console.log("connected");
});
If I add the get request after exporting the static files, the console.log never gets called. If I use it before, it does get called, but I can see the page loading forever. How should I structure the application now that I'm using react and I don t have a view engine anymore?
In your specific case, if you don't want to render anything to the user, you should turn your function into a middleware :
app.get("/",function(req,res, next){
console.log("connected");
next();
});
and put it before the app.use(express.static('./public'));
However, if you want to do actual logic with return values and such, I would suggest that you setup some kind of API that you request using Ajax from the client.
You can check my repository
https://github.com/kennethmervin01/react-node-production
it's a boilerplate to serve react app in node.js/express
then check my code inside app.js
You just need to copy the production build of your react app inside the react folder
app.use(express.static(path.join(__dirname, "../react")));
app.get("/*", (req, res) => {
res.sendFile(path.join(__dirname, "../react", "index.html"));
});

Ember and Express: let Ember handle routes instead of Express?

This might be a dumb question, but I'm serving an Ember app I made using ember-cli on an Express server, but when I try to access various routes, my Express app errors, saying that no route exists (which is true, because I defined the routes in Ember, not Express). How should I resolve this, and is this normal behavior?
My Ember router:
Router.map(function() {
this.route('index', {path: '/' });
this.route('portkey');
this.route('login');
});
My Express routes are just an API that do not serve any of the Ember routes, since localhost:1234 will automatically load index.html.
I've never had a problem using the Ember Router instead of the Express router. All I do is have 1 express route (for '/') which displays my Ember application index.html (well actually index.ejs) page. Not promising this is the right way to do it, but it's how I do it and it works for me.
So start with this.
app.get('/', function(req, res) {
res.render('index', {});
});
That's your express route. Now your ember routing.
App.Router.map( function() {
this.route("about", { path: "/about" });
this.route("favorites", { path: "/favorites" });
});
So as of now you have a routing structure that looks like the following:
yourdomain.com/ --> index.ejs displayed via express routing
/#/ --> this is the ember index route
/#/about --> this is the ember about route
/#/favorites --> this is the ember favorites route
Within the index.ejs file you have the basic ember file linking to your ember application.
Now onto your linking problems...
If you use the ember router, then make sure you are linking to your different routes the correct way. (Remember, ember routes start with /#/someroute).
So your links in handlebars should be something like:
{{#link-to 'some_page'}}Go to some page{{/link}}
NOT
Go to some page
Using the second, express would be trying to handle the routing but by using the first, ember is handling the routing.
So if you really think about it, you can have as many ember applications as your little heart disires because each ember application is linked to that current page in the express routing.
For example on my website, I use two routes (plus a bunch of REST routes obviously): login.ejs and index.ejs.
So for my site, I have the following routes:
mysite.com/
/#/
/#/budget
/#/history
/#/profile
/#/logout
mysite.com/login#/
#/register
#/forget
I hope this helps you a little bit.
EDIT
/#/ is a convention to tell ember you are routing via its router.
Think of it like this: Ember is a single-page framework. So when you link from page to page in ember, you aren't truely changing pages. You are just removing dom elements and replacing them with new ones. But if you go to /budget on the server, you are now going to a whole new page, not just the /#/budget section of the ember application.
I think you are just confusing what the ember router really is.
I had similar issues when trying to directly access any part of my Ember project other than index.html. From there I could easily navigate where I wanted, but it meant that providing someone a link or refreshing the page would fail.
Example: /accounts would fail.
/#/accounts would successfully redirect to /accounts however refreshing still would not work.
Solution:
Router.map(function() {
this.route('accounts');
});
Router.reopen({
location: 'hash'
});
Now all of my links are prefixed with # such as /#/accounts, refreshing and direct-linking works as expected.

How to use AngularJS routes with Express (Node.js) when a new page is requested?

I'm using Express, which loads AngularJS from a static directory. Normally, I will request http://localhost/, in which Express serves me my index.html and all of the correct Angular files, etc. In my Angular app, I have these routes setup, which replace the content in an ng-view:
$routeProvider.when('/', {
templateUrl: '/partials/main.html',
controller: MainCtrl,
});
$routeProvider.when('/project/:projectId', {
templateUrl: '/partials/project.html',
controller: ProjectCtrl,
});
$locationProvider.html5Mode(true);
On my main page, I have a link to <a href="/project/{{project.id}}">, which will successfully load the template and direct me to http://localhost/project/3 or whatever ID I have specified. The problem is when I try to direct my browser to http://localhost/project/3 or refresh the page, the request is going to the Express/Node server, which returns Cannot GET /project/3.
How do I setup my Express routes to accommodate for this? I'm guessing it will require the use of $location in Angular (although I'd prefer to avoid the ugly ?searches and #hashes they use), but I'm clueless about how to go about setting up the Express routes to handle this.
Thanks.
with express 4, you probably want to catch all requests and redirect to angularjs index.html page.
app.use(app.router); doesn't exist anymore and res.sendfile is deprecated, use res.sendFilewith an uppercase F.
app.post('/projects/', projectController.createProject);
app.get('/projects/:id', projectController.getProject);
app.get('*', function (req, res) {
res.sendFile('/public/index.html');
});
put all your API routes before the route for every path app.get('*', function (req, res){...})
I would create a catch-all handler that runs after your regular routes that sends the necessary data.
app = express();
// your normal configuration like `app.use(express.bodyParser());` here
// ...
app.use(app.router);
app.use(function(req, res) {
// Use res.sendfile, as it streams instead of reading the file into memory.
res.sendfile(__dirname + '/public/index.html');
});
app.router is the middleware that runs all of your Express routes (like app.get and app.post); normally, Express puts this at the very end of the middleware chain automatically, but you can also add it to the chain explicitly, like we did here.
Then, if the URL isn't handled by app.router, the last middleware will send the Angular HTML view down to the client. This will happen for any URL that isn't handled by the other middleware, so your Angular app will have to handle invalid routes correctly.
I guess I should have clarified that I wasn't interested in using a template engine, but having Angular pull all of the HTML partials on it's own, Node is functioning completely as a static server here (but it won't be for the JSON API. Brian Ford shows how to do it using Jade here: http://briantford.com/blog/angular-express.html
My app is a single-page app, so I created an Express route for each possible URL pattern, and each of them does the same thing.
fs.readFile(__dirname + '/public/index.html', 'utf8', function(err, content) {
res.send(content);
});
I was assuming I would have to pass some request variables to Angular, but it looks like Angular takes care of it automatically.

Resources