I'm building a site with MEAN stack, and overall this is my structure:
root
app
auth
auth.routes.ts
auth.service.ts
app.component.html
app.component.ts
app.routing.ts
On my app.routung.ts I have this code:
const APP_ROUTES: Routes = [
{ path: '', redirectTo: '/main_url', pathMatch: 'full' },
{ path: 'main_url', component: MainComponent, canActivate: [AuthenticationGuard] },
{ path: 'cars', component: CarsComponent },
{ path: 'auth', component: AuthenticationComponent, children: AUTH_ROUTES },
];
Then, in my app.js main file I have these routes:
app.use('/main_url', mainRoutes);
app.use('/cars', carRoutes);
app.use('/', appRoutes);
The content of appRoutes is this:
var express = require('express');
var router = express.Router();
router.get('/', function (req, res, next) {
res.render('index');
});
module.exports = router;
The index file, renders an html with a menu on the left sidebar. In the content part, I have a <my-app>Loading...</my-app>, which loads the app.component.ts and all the logic there.
The question here is, how can I secure my index.html main route, with a login page, when I don't want to include it inside my <my-app>Loading...</my-app>?
I'm I doing something wrong? Or there is a good way to do that?
UPDATE
A brief description of my problem:
I have a node router, which only has a get method, then, is redirected to index:
... code ...
res.render('index');
index.html, is a template with a header, sidebar menu, footer and content. In the content, I have this: <my-app>Loading...</my-app>, this line triggers my angular component, which uses my Angular Routes (APP_ROUTES), the one I posted before.
All at this point works fine, but, how can I prevent to trigger the index.html from my res.render('index'), when the user is not logged in and send it to a complete separated login.html page/code? I think I have to change something because always I'm going to be redirected to index, no matter what, because it is the entry point.
Please try Angular's HashLocationStrategy, which puts a '#' in the URL to separate the bit's the server responds to from the bits Angular responds to (to put it crudely).
Ng-book gives a good description, the essentials are
import {LocationStrategy, HashLocationStrategy} from '#angular/common';
#NgModule({
declarations: [
...
],
imports: [
...
],
providers: [
provide(LocationStrategy, {useClass: HashLocationStrategy})
]
Please also see the answer to this SO question, which mentions server configuration (as an alternative).
Ensure your server is configured to support HTML5 pushState. This just
means that the server returns index.html for requests to unknown
resources.
Here is another good reference Location Strategies in Angular Router, probably the best I can find to describe the problem.
Related
I am trying to open page in new tab, in local it was working fine when deployed to server getting error as below:
Oops, looks like the page is lost.
This is not a fault, just an accident that was not intentional.
Below is my code:
Router:
const routes: Routes = [
{ path: ' ', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: HomeComponent },
{ path: 'resource', component: ResourceDetailsComponent },
{ path: 'careers', component: CareerComponent }
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
In component:
<a class="view" (click)="redirect(a)"
>VIEW MORE VACANCIES</a
>
redirect(){
localStorage.removeItem("selectedCareer");
window.open("/careers", '_blank');
}
In local page is redirecting and working fine, anything i have missed in my code please let me know.
You are probably trying to access some suburl like yourhomepage.com/resource right?
Your local Development Server will always serve the index.html per default and you probably want to configure your deployment server the same way. You need the index.html file to be served for your angular spa to work. Without knowing your Provider/Server there is no real way to help you with that.
Most Webservers are configured to always return the file you are accessing through the url or the index.html if you provide no suburl.
So if your file tree looks like this:
index.html
angular.js
yourhomepage.com and yourhomepage.com/index.html will return the index.html
and yourhomepage.com/angular.js will return the js file.
BUT yourhomepage.com/ressouces will not return anything because there is no corresponding file. But you can configure your Webserver to also return the index.html in that case.
This is what you probably have to do.
I'm pretty new to VueJS and have a problem I can't grasp right now.
I coded a little App which works absolutely fine under vue serve, but when I build it and upload the dist folder to my webserver I'm experiencing a weird problem.
I have the following Routes:
/home
/overview
/listing
/detail
I start at home, click on a button go to overview, from there to listing and from there to detail. Every template has a a "Go Back" Link which works with
#click="$router.back()"
When testing locally with Vue Serve it behaves as expected.
When I built it and upload the dist folder I get the weird error that when I'm on "Detail" and go back, it goes to "Overview" instead of "listing". I notice that the address in the browser is always one level "off". For example if I go back from overview to home, it shows the home-template but the addressbar shows /listing.
Does anyone have an idea what I'm doing wrong? Thanks a lot!
I already tried $router.go(-1), which results in the same error..
My router file looks pretty standard I'd say:
{
path: '/home',
name: 'Home',
component: Home
},
{
path: '/overview',
name: 'Overview',
component: Overview
},
{
path: '/listing',
name: 'Listing',
component: Listing
},
{
path: '/detail',
name: 'Detail',
component: Detail
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
It works great in vue serve mode, but just not when using the dist folder online..
I created a new Vue app with a base path. Due to the fact the app is embedded into another Vue app, this app doesn't render the router-view on startup. If you want to know more about how or why this app is embedded into another app, please have a look here:
mount Vue apps into container of main Vue app
and my own answer to this problem:
https://stackoverflow.com/a/58265830/9945420
When starting my application, it renders everything except the router-view. I want to redirect on startup by the given browser URL. This is my router config:
import Vue from 'vue';
import Router from 'vue-router';
import One from './views/One.vue';
import Two from './views/Two.vue';
Vue.use(Router);
const router = new Router({
base: '/my-embedded-app/',
mode: 'history',
routes: [
{
path: '/',
component: One,
},
{
path: '/two',
component: Two,
},
],
});
router.replace(router.currentRoute.fullPath);
export default router;
I want the app to render the component Two when calling .../my-embedded-app/two. Unfortunately, router.replace always redirects to / (so the browser URL is .../my-embedded-app/). I debugged the router, and saw that the path is /, but I would expect it to be /two.
Important note:
I don't want to redirect the user to /two whenever the url is /. I just want to render the view Two when the url is /two. Currently it doesn't.
What might be wrong? Maybe I don't even need that redirect, and can solve the problem a more elegant way.
updated: jsfiddle
What wound up happening is that route.currentRoute.fullPath was executed before router was ready.
That's the normal behavior, it is the way single page application works. The "pound" - like # - sign means that the links will not move the application to another page.
so you can change the router mode to
mode:"hash"
Try beforeEnter. Have a look at the below code:
const router = new Router({
base: "/my-embedded-app/",
mode: "history",
routes: [
{
path: "/",
component: One,
beforeEnter: (to, from, next) => {
// Your are free to add whatever logic here.
// On first visit
next("/two");
}
},
{
path: "/two",
component: Two
}
]
});
Read more about Navigation guards here
Could you provide a github repo or some to test the actual?
Otherwise my first idea is to use children routes with an "empty" view as base, here an example about what I tried. (working in my case)
router.js
export default new Router({
mode: 'history',
base: '/my-embedded-app/',
routes: [
{
path: '/',
name: 'base',
component: Base,
children: [
{
path: '',
name: 'one',
component: One
},
{
path: 'two',
name: 'two',
component: Two
}
]
}
]
})
Base.vue
<template>
<router-view/>
</template>
One.vue
<template>
<div>One</div>
</template>
Two.vue
<template>
<div>Two</div>
</template>
I am creating a NotFoundComponent so that every non-existing url, a friendly page will apear to the user.
My Angular 6 project has 5 features(CRUDL):
CompanyComponent,
EmployeeComponent,
BranchComponent,
BenefitsComponent,
MainComponent
Each component have it own .module and .routing, for example the company.routing.ts defines the route like this:
export const routes: Routes = [
{
path: "branch",
component: EmptyComponent,
}
...
#NgModule({
imports: [
RouterModule.forChild(routes),
...
it also defines its childrens, like path: "branch/:id".
So, i have no problem with the way i built the routing.
The problem I am facing now is the way I can define a path to the NotFoundComponent.
Because I don't have a single file where I define my routes, if I put the definition of the /404 page on the on the bottom of routers definition in the main.routing.ts, every other route defined on the features(like the company.routing.ts) will be redirected to the /404, since angular uses the first match strategy.
Things i tried so far:
on the main.routing.ts:
export const routes: Routes = [
{
path: "main",
component: MainComponent,
},
{
path: "404",
resolve: {
routeTitle: TitleResolver,
},
component: NotFoundComponent,
},
{
path: "",
pathMatch: "full",
redirectTo: "/main",
},
{
path: "**",
redirectTo: "/404",
}
if I put this way, when I try accessing the route /company (defined in the company.routing.ts) it will be redirected to the /404.
I also tried defining it on any a routing of one of my features, like on the company.routing.ts
{
path: "**",
redirectTo: "/404",
}
Than, a funny thing happened, if I define this piece of code on the benefits.routing.ts, i can access /benefits but /branch, /employee and the rest of the routes will be redirected to /404.
if I define it on branch, I can access /benefits, /branch but /employee and the rest of the routes will be redirected to /404.
I could just place this code on the last feature loaded and it would work but I would like to know if I can solve this with another approach, can't I define a route that I want to be the last one loaded?
thanks in advance.
I have a feature module that I load in the AppModule, the AppRoutingModule looks like
const appRoutes: Routes = [
...
{
path: 'move-request/:id',
loadChildren: 'app/modules/move_requests/move_requests.module#MoveRequestModule'
},
...
];
And the configuration of routing for the feature module looks like
const moveRequestRoutes: Routes = [
{
path: '',
component: MoveRequestFormComponent,
data: {title: 'Move Request'}
},
{
path: 'move-request-success',
component: RequestSuccessComponent,
data: {title: 'Move request success'}
},
];
I would like to navigate to MoveRequestFormComponent as the default component when move-request/:id is routed to, this works fine, but when I call
this.router.navigate(['/move-request-success', {}]);
In MoveRequestFormComponent after some response from the server, I get
zone.js:665 Unhandled Promise rejection: Cannot match any routes. URL Segment: 'move-request-success' ; Zone: <root> ;
This configuration was working before I switched to Angular 6, Is it because of the change in the AppModule, where I have excluded this feature module as an import?
Any assistance on what I am missing would be much appreciated. As I have also tried with having a third component which will be the default component and uses the router-outlet to render the children and have a children property on this route to have as children
{
path: '',
component: MoveRequestFormComponent,
data: {title: 'Move Request'}
},
{
path: 'move-request-success',
component: RequestSuccessComponent,
data: {title: 'Move request success'}
},
But that also did not work, it stayed on the MoveRequestFormComponent, when 'move-request-success' was navigated to.Or maybe I should change the approach?
You don't have to import the feature module in AppModule as it is lazily-loaded. When you navigate to move-request/:id/move-request-success, the path matches the default route with path:'', and then it will look for and children of that route. You should add pathMatch:'full' to the first route, which is the default in this case. Since the mentioned route matches the first route and is unable to find and match any children, it is showing the error.
this.router.navigate(['/move-request-success', {}]);. If you add a / to a route this means you use absolute path from root. Have you tried without / ?
EDIT:
I think I see your problem. You navigate to a module with multiple components, which means after lazy loading the router configuration from the loaded module is used. This means
move-request/:id
Is the root of your module and every subroute needs to include the modules root in the url:
Your route should be move-request/:id/move-request-success
Urls in lazy loaded modules are:
module root (in your case move-request/:id) + configured route of the specific component (in your case move-request-success)