My app works fine with ngRoute, but when I'm trying to access my parts directly(from address bar), it returns just the part (without main page). How to hide these parts from a direct access?
Explanation:
I have a site with 2 blocks. First is a menu and second is a content (one of my route's part). Menu has links: "#/main" and "#/account". When I press on the buttons, it works fine (left menu and content). But if I change URL from localhost:8080/#/account to localhost:8080/account, it renders ONLY content, without menu. I want to hide access to localhost:8080/account or make it to render a content with a menu.
Your problem is most likely not with your AngularJS routing, but the routing from the server. When you request a page like localhost:8080/account, your server says "ok, let's JUST deliver the /account file". But that's not quite right, because you actually want the whole app to load. It's a common problem, and not too bad to solve.
I don't know what your backend looks like, but here's a generic example with express/node:
var express = require('express'),
routes = require('./routes');
app.get('/', routes.index);
app.get('*', routes.index);
"Every request to the backend should initially render the complete layout in order to load our Angular app. Only then will the client-side rendering take over."
src: http://fdietz.github.io/recipes-with-angular-js/backend-integration-with-node-express/implementing-client-side-routing.html
Related
I am using AngularJS in the client side combined with ExpressJS in the server side.
When pages are loaded in the browser all works fine there: clicks on the various button and differents angular routers are okay.
The problems come when a generated url need to be put in the address bar manually.
Here are the details of this scenario:
the server generates a URL (e.g. "http://localhost:9000/details?card=5" and sends it via email
I receive the email, open the url from it
the browser opens on "/" instead of staying on "/details" internal/client route
On the details.controller.js of details.html (client side) I can see that the request for card number 5 is sent and arrives to the server (so I am almost sure that the details.html page is loaded) but angular routing must be very quick relocating the user view on "/".
I am not sure on the exact flow, but I am assuming that:
click on the link in the email
the OS or email client redirect "http://localhost:9000/details?card=5" to the browser
the browser receives "http://localhost:9000/details?card=5" and performs a GET to the server
the server receives the GET above
maybe the server is calling "/index.html" since express static is configured as:
app.use(express.static(path.join(__dirname, config.client.path), {
index: 'index.html',
}))
Maybe I am little confusing something, the project is not mine and I have not so many skills in (the very old) AngularJS.
Could someone explain to me how the server could "say" to the client to move on the angular "/detail" route (including the query param card)?
I'm running an express server and if no other certain URLS aren't met, the user is redirected to the React App:
app.get("*", verify, (req, res) => {
if (maintenance) {
return res.sendFile("./maintenance.html", { root: __dirname });
}
return res.sendFile(
path.resolve(__dirname, "../frontend/build", "index.html")
);
});
This successfully runs the verify middleware needed to check if the user making the request is logged in, if not it redirects them to another service for them to login.
I would've thought that since all URLS that are being used are going through the whole web app is going through this express server, the verify middleware would've been executed no matter what page the user is on. However, this middleware is only executed upon either opening the site on a browser that hasn't been to the site yet (not cached) or if the user force refreshes the page.
I'm new to React and this has led me to believe that React loads the whole app, and upon each change of page (for example from /home to /profile) it doesn't change the url, just loads the portion of the app that's already loaded and so no matter what page the user is on, express will always see that the user is only on the root domain.
How would I get pass this without doing any of this logic on the frontend side. E.g. run the verify function before each page on the react app is loaded into view
Since React is all client side rendering you will need to handle that middleware in your React router, not your Node router. On the frontend we call this "middleware" protected routes.
The overall point is, you will need to protect those routes on the frontend, as when you change a page in React, Node does not know about it (because React is client side rendered).
I am pretty new to the node.js and express.js landscape. However I have been trying to wrap my head around the code behind creating a site (20+ pages for example) in express.js without the code getting pretty large.
A route, when using a view engine, points the incoming request to index or whatever page they requested. After running the default express-generator with the view engine set to HBS you get something like
app.use('/', index);
This points to the index.js file under the routes folder that contains something like
router.get('/', function(req, res, next){
res.render('index', {title: 'Express'});
});
And that then renders the index.hbs file to show what I want on the page.
My problem is this. Would you have to have a route for each page you wanted like a profile page, login page, about page, etc? If so wouldn't this create a lot of lines of code in routes if you had 20+ routes? Example would be in the app.js
app.use('a', a);
app.use('b', b);
...
app.use('z', z);
then each would require a corresponding route js file.
I assume there is a cleaner way of doing routing or perhaps I am over thinking this?
Any light on this concern/question of mine would be amazing.
In my express servers I break routes into different sections called "components" Each components can correspond to a give page if you're doing server-side rendering or it can correspond to a set of API routes.
Each component can have controllers to handle each route, and each controller can borrow from a handful of reusable actions.
Here's an example of an express server component I made(this example is for a set of API routes but the same architecture can be used for sets of hbs server-side rendering routes):
https://github.com/AkyunaAkish/react-redux-node-express-todo-list-boilerplate/tree/master/server/components/todos
It depends on how similar your routes are:
If they basically all have the same functionality, I'd put them in the same file.
If there are slight variations, I'd create a separate class containing the core functions, and then call to what ever is needed separately.
If they are completley different, put them all in separate files
This will give you a solid outline of how to do each:
How to include route handlers in multiple files in Express?
Node.js: Configuration and routes in a different file
How to include route handlers in multiple files in Express?
Generally, you make route files around areas of concern, though a given router can define whatever endpoints make sense. So for example, let's say your site has several pages that are fairly static (e.g. your "about" and "index" examples, and then several that are all based on blog entries (creating, listing, viewing, etc) and then several around users (user profiles and so on). You would probably create one router for each set of things, e.g.:
// ./routes/index.js
router.get('/', (req, res) => { res.render('index', {title: 'Express'}); });
router.get('/about', (req, res) => {res.render('about', {title: 'Express'});});
// etc
conceptually, you could use that more simply to pull the "index" or "about" values from the URI, but I'm assuming you'll do other things like assigning variables and such.
Then in another file
// ./routes/blog.js
router.get('/blog', (req, res) => {
// do whatever to fetch info fromt eh DB and render it...
});
And so on.
I'm trying to design a Single Page App using Node.js that has multiple tabs, and on each tab can contain a number of images or scripts, so I'd like to prevent loading the content of every tab each time a user visits the page. So ideally when a user switches tabs the server would send the html which contains the images and scripts and the client would display that without reloading the page.
The reason I chose the SPA design is that outside the tabs would be a chat system amongst other things running in the background that I don't want to resend to clients each time a redirect happens.
So my question is what is the best way to send the html, or is there a better way in general that still uses the SPA design?
Would the best way be to send the html in the router to the client, then use ajax to prevent a page refresh and add new tab html and remove old tab html after that?
You can use Express.js with only one route.
This route could be called:
var app = require('express')();
app.get('/',function(req, res) {
res.sendFile(path.join(__dirname + '/index.html'));
}
Note that:
This is a GET route
It just sends the file contents with sendFile
After that you can have many API routes to fetch the data for your tabs. I would recommend these routes to be like this:
app.post('/about',function(req, res) {
res.json({ data: "your data here" });
}
app.post('/contact',function(req, res) {
res.json({ data: "your data here" });
}
On these routes note that:
These are POST routes
Only a JSON is returned
SPA means "single page app", and you will only have a single HTML shell that a JavaScript framework will then handle the "pages" and HTML after that
I want to restrict a certain subtree only to authenticated users. The basic setup is as follows (fat removed):
app.use(express.bodyParser())
.use(express.cookieParser('MY SECRET'))
.use(express.cookieSession())
.use('/admin', isAuthenticatedHandler)
.use('/admin', adminPanelHandler);
Where the handler functions is:
isAuthenticatedHandler = function(req, res, next) {
if (!req.session.username) {
res.redirect('login');
} else {
next();
}
};
The problem is that even though I provide the redirect destination as a relative path 'login', it doesn't lead to <mount_point>/login i.e. /admin/login but to /login which of course throws a 404.
From the expressjs API reference:
This next redirect is relative to the mount point of the application.
For example if you have a blog application mounted at /blog, ideally
it has no knowledge of where it was mounted, so where a redirect of
/admin/post/new would simply give you `http://example.com/admin/post/new`,
the following mount-relative redirect would give you
`http://example.com/blog/admin/post/new`:
res.redirect('admin/post/new');
Am I misreading this?
The issue here is that while you are using your middleware off of /admin, your app itself is not mounted at /admin. Your app is still off of the root, and your configuration simply says to only use your isAuthenticatedHandler middleware if the request comes in off the /admin path.
I whipped together this gist. Notice how it uses 2 Express applications, one mounted inside the other (line 23 pulls this off). That is an example of mounting the application at a different point rather than just putting a given middleware at a given point. As presently written, that example will give you an endless redirect, since the isAuthenticatedHandler fires for everything off of / in the child application, which equates to /admin overall. Using 2 separate applications might introduce other issues you're not looking to deal with, and I only include the example to show what Express means when it talks about mounting entire applications.
For your present question, you'll either need to follow what Yashua is saying and redirect to /admin/login or mount your admin interface as a separate Express application.
What are you trying to achieve? Why not just redirect to '/admin/login' ? And the mount point they are talking about is the place where your Express app is located, not necessarily the current URL. So /blog might be setup on your server to be the root of your app while / might be a totally different app. At least that's the way I read this.