How does vue routing make the 404 page jump to the outside site? - vue-router4

A common configuration is this:
{path:'/*', name:'404', component:()=>import('#/views/404.vue')},
This will jump to a vue page, but now I want to jump to a public 404 page outside the site, how do I do it?
Tried this, doesn't work:
{path:'/*', redirect:'http://*.com/404.html'},
The current method is to enter 404.vue first, and then run window.location.href="http://...."
I want to ask the big guys, can you set it directly in the routing table?

Use this code in your router
{path:'*', name:'404', redirect:()=>{ window.location.href="some-url"}}
or
{path:'*', name:'404', component:()=> {window.location.href="some-url"}}
or if you want your component, instead of using redirect use your 404 vue component in your router
{path:'*', name:'404', component:()=>import('#/views/404.vue')}
Then in your 404.vue component in beforeCreate Lifecycle Hooks add this code
<script>
export default {
beforeCreate() {
window.location.href = 'some_url'
},
};
</script>

It seems impossible.
But you can write components directly in the route here.
{path:'/*', name:'404', component: function(){window.location.href="http://sf.gg"}}

Related

Don't redirect on POST express.js

I'm making a basic web app with Node.js and Express 4 and I'm trying to implement a "follow" function. I did some inspecting on the Github website and noticed it used a form with a follow button that would post to the server to follow a user. I think this sounds like a good approach but when I post I don't want to have to reload the page just like the github website.
How does one this inside of Express 4? Everything I put inside the .post route always end up in a page load. I'm pretty sure in jQuery's ajax method you can just return false and nothing will happen to the page, just the request will be sent which is what I want to happen because I'm using a RESTful api and I want to add the user to the current user's following but I don't want to have to use jQuery just for this function. I would prefer it be done in Express if possible, though any help would be appreciated.
views/user.handlebars
<h1>{{user.displayName}}</h1>
<p>#{{user.username}}</p>
<form action="" data-userid="{{user._id}}" method="post">
<button name="follow" type="submit">Follow</button>
</form>
routes/users.js
app.route('/:username')
.get(function(req, res) {
// get :username user from api and load info
...
})
.post(function(req, res) {
// don't reload page
???
// send PUT :username user to current users following array
...
});
So you're on the right track, but instead of putting your actions in the HTML (in your jade file) you're gonna have to add a script section to your jade and use javascript to attach an onClick event to the button so that when you press the button you invoke your ajax method.
Let me know if that doesn't make sense.

Use dynamic express routes within another Express route

For a school project, I created a plugin system for an Express.js-Application in Node.js. The main page of the application should display a dashboard, where every root page of each plugin should be displayed in a div. Every root page is accessible over the pluginName/-route.
What I would like to do is the following: I wanna include the HTML-string of every home-route in the dashboard. But for this, I need to call the routes inside Node.js (like partials) and for some plugins I even have to provide some properties.
Does someone have an idea, how this could be implemented?
e.g. I have following route:
router.get('/pluginName', function(req, res) {
res.render(__dirname + '/views/home.handlebars', {
layout: __dirname + '/views/layouts/main.handlebars',
markup: markup // Pass rendered react markup
});
});
Now I want to pass the resulting HTML from this route into another route.
So far I had the following ideas:
Simply add the URLs of the plugins to a "data-ajax-url" attribute of the divs and load the stuff via AJAX.
Make an HTTP-Call to every route and append the result on server side (pretty nasty...).
Create a renderDashboard-function for every plugin, where I get the HTML using app.render(...) and then I append the result.
But I'm not really sure, which approach (if any) would be the nicest.

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.

Angular and Sails routing configuration

Is there any Sails.js (or Node) configuration which can prevent Angular routing from working?
No matter what approach I take, every rout apart from ones in sails' routes.js return 404.
I've tried both 1.2 and 1.3 Angular versions, and I'm using Sails v 0.9.15.
All scripts are loaded in correct order (for example):
<script src="/linker/js/libs/angular/angular.js"></script>
<script src="/linker/js/libs/angular/angular-resource.js"></script>
<script src="/linker/js/libs/angular/angular-route.js"></script>
<script src="/linker/js/libs/angular/angular-sanitize.js"></script>
...
<script src="/linker/js/app.js"></script>
I'm using the ngRoute correctly:
var myApp= angular.module('myApp', ['ngRoute']);
Here are my routes in Angular's app.js:
myApp.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/profile',
{ templateUrl: 'linker/views/profile.html', controller: 'MainCtrl' })
.when('/profile-detail',
{ templateUrl: 'linker/views/profile_detail.html', controller: 'MainCtrl' });
}]);
And I'm also using location provider:
myApp.config(function ($locationProvider) {
$locationProvider.html5Mode(true);
});
Additional details:
ng-app and ng-view are correctly placed, and my paths are correct. I can correctly show profile.html with Angular (and also to include data from Sails' Restful API).
Problem is, that I can only do that for routes defined in Sails' routes.js.
Example:
module.exports.routes = {
'/' : {
controller: 'main',
action: 'index'
},
'/signup' : {
controller: 'main',
action: 'signup'
},
'/login' : {
controller: 'main',
action: 'login'
},
'/profile': {
controller: 'users',
action: 'profile'
} //......
So basically, in order to show some html content with Angular, I have to define EXACTLY THE SAME route in Sails' configuration, which makes no sense.
Any ideas? P.S. I'll provide additional data if needed.
Try removing the html5 mode to see what happens:
$locationProvider.html5Mode(false);
If you are using your sails application only to provide an API for your Angular app, but you are using the same backend to serve your angular code, then you could prefix all API routes with 'api' in order to prevent having conflicts with angular routes.
Instead of /profile you would have /api/profile
EDIT:
I've taken a look into the Sails.js framework and made a small app to test it.
I was able to successfully have routes in angular work that were not defined by sails.
I think there is a misunderstanding of how angular routing works.
If you change the path with window.location or type the url manually, the browser will send a get request to the server. So in your case, there will be a request for /profile or /profilee and the server will look at the available routes and will throw a 404 if nothing matches.
To prevent that, you should actually change the path using angular methods. Angular uses the '#' symbol in the path to prevent the browser of sending requests to the server when the url changes. Browsers ignore changes after the '#' symbol. Or in your case, a similar effect is achieved using the html5 mode. Beware though that using html5 mode can cause troubles when users refresh the page, since then a request will be made to the server (more on how to fix that below).
So, what you should be using to change the paths with javascript is the $location service. In your angular views, you can also use normal anchor tags like, because angular parses those:
Go to profile
Since what you have is a single page application, alls views are handled by the client. All the paths beyond the root (/) are virtual paths created by angular. They usually don't exist in the server. Only the root is available. When using html5 mode that can be a problem.
A way to fix that is to rewrite the routing of the server to serve everything else as if it was a request to the root path. In sails they even suggest how to do that in the config/routes.js:
// What about the ever-popular "vanity URLs" aka URL slugs?
// (you might remember doing this with `mod_rewrite` in Apache)
//
// This is where you want to set up root-relative dynamic routes like:
// http://yourwebsite.com/twinkletoez
//
// NOTE:
// You'll still want to allow requests through to the static assets,
// so we need to set up this route to ignore URLs that have a trailing ".":
// (e.g. your javascript, CSS, and image files)
'get /*(^.*)': 'UserController.profile'
Regarding the API in sail, you can configure a prefix inside the config/controllers.js file:
/**
* `prefix`
*
* An optional mount path for all blueprint routes on a controller, including `rest`,
* `actions`, and `shortcuts`. This allows you to continue to use blueprints, even if you
* need to namespace your API methods.
*
* For example, `prefix: '/api/v2'` would make the following REST blueprint routes
* for a FooController:
*
* `GET /api/v2/foo/:id?`
* `POST /api/v2/foo`
* `PUT /api/v2/foo/:id`
* `DELETE /api/v2/foo/:id`
*
* By default, no prefix is used.
*/
prefix: '',

How to use Backbone with Jade correctly

Hi I´m developing a expressjs backbonejs with mongoose, my template engine is HTML (with text.js).
My app have a navbar with Register and Login links and a container where I put contents. I implemented a login system with passportjs, it works well, when you are logged in you´ll have a req.user object with your user info.
Now I´m blocked cause I´d like to hide the navbar links if I´m logged in.
When I did the POST to /login if all is success, i redirect to /account and load another view with it template, I´ll have the req.user data but the navbar view doesn´t have it and then I can´t hide the links.
I tried to pass to jade cause I can put the HTML code of the navbar in a template and after POST /login render a jade template that contains the navbar template with "extends". But in this cause I lost all my Backbone functionality cause I can´t navigate with # in the URL.
Wich is the correct way to do this?
Hope you understand me, regards.
You may solve the situation by using singleton pattern. I.e. a global config object which has a method isLogged for example. The idea is to initialize this object in the entry point of your application. The place where you have the needed data and later access it via that singleton. For example:
var AppConfig = (function() {
var isLoggedFlag = false;
var changeLoggedStatus = function(value) {
isLoggedFlag = value;
}
var isLogged = function() {
return isLoggedFlag;
}
return {
isLogged: isLogged,
changeLoggedStatus: changeLoggedStatus
}
})();
When you know that the user is logged just use:
AppConfig.changeLoggedStatus(true);
In your view just check
if(!AppConfig.isLogged()) {
// hide whatever you need to
}

Resources