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.
Related
I'm using multiple named angular 8 router-outlet in a web app. All the routerLink seems to work as it changes the URL but components in my 2nd router-outlet are imported but not initialized nor rendered.
I made a Stackblitz available here : https://stackblitz.com/edit/ng-multiple-router-outlet?file=src/app/app.component.ts
As you can see, when you click on the sidebar, under photos you have a second navigation level by clicking on Google or Facebook but nothing is rendered.
In modules, components used in other modules and RouterModule are well exported to be accessible, I don't see what I've done wrong.
I tried to declare the routes with both forRoot and forChild methods, I put some logs, but I'm running out of clues.
Thanks for your help !
Angular router is pretty simple once you understand how nested routes works there.
Let's imagine a simple configuration:
RouterModule.forRoot([
{
path: '',
component: HomeComponent,
children: [
{ path: 'child', component: ChildComponent }
]
}
])
How would you use router-outlet to cover all routes above?
app.component.html
\
contains
\
<router-outlet></router-outlet>
\/
renders
\
HomeComponent
home.component.html
\
contains
\
<router-outlet></router-outlet>
renders
\
ChildComponent
The main takeaway here is that router-outlet renders component depending on router context. Once it renders component a new context is created and all router-outlet's declared at this level will look at children configuration.
The same is true for named routes.
You've generated the link like:
(selection:facebook//sidebar:photos)
It means that these named routes should be at the same root level. But you defined <router-outlet name="selection"></router-outlet> at nested level inside rendered by router LibraryComponent.
Let's add this outlet at the same level as 'sidebar':
<router-outlet name="sidebar"></router-outlet>
<router-outlet name="selection"></router-outlet>
and it actually works stackblitz
Now let's come back to your attempt. If you want to render selection components inside selection.component.html then you should be using nested named routed links:
selection.component.html
[routerLink]="['.', { outlets: { selection: [routeName] } }]"
\/
relative path
The above binding will generate nested links like (sidebar:photos/(selection:facebook))
Now you need to move SelectionRoutes configuration to children property of photos path:
selection.module.ts
imports: [
CommonModule,
RouterModule, //.forChild(SelectionRoutes)
],
sidebar.routes.ts
import { SelectionRoutes } from '../selection/selection.routes';
...
export const SidebarRoutes: Route[] = [
{ path: 'photos', component: LibraryComponent, outlet: 'sidebar', children: SelectionRoutes },
Stackblitz Example
Update
In order to make facebook as a default subroute you create a route with redirectTo option like:
export const SelectionRoutes: Route[] = [
{ path: 'facebook', component: FacebookComponent, outlet: 'selection' },
{ path: 'google', component: GoogleComponent, outlet: 'selection' },
{ path: '', redirectTo: '/(sidebar:photos/(selection:facebook))', pathMatch: 'full', },
]
Stackblitz Example
I've been struggling with this issue for the past day and a half and still have made no progress. Currently, I am attempting to load my angular app and have it default to a particular page when the application is bootstrapped. Unfortunately, it redirects to a different route.
I'm trying to go to:
https://clwd0002278/ControlTower/NICK/UI/#/
When I initially load, though, it goes to https://clwd0002278/ControlTower/NICK/UI/#/ControlTower/NICK/UI/, which results in the 404 page being hit.
I'll also try to go to https://clwd0002278/ControlTower/NICK/UI/ with the same result as above.
Here's the code so someone can try to make sense of this:
const routes: Routes = [
{path: '', redirectTo: 'patients', pathMatch: 'full'},
{path: 'dashboard', component: DashboardComponent},
{path: 'notifications', component: NotificationsComponent},
{path: 'patients', component: PatientListComponent},
{path: '404', component: NotFoundComponent},
{path: '**', component: NotFoundComponent},
];
#NgModule({
imports: [
RouterModule.forRoot(routes, {useHash: true})
],
exports: [RouterModule]
})
export class AppRoutingModule {
}
Here's the base-href on the html page:
<base href="#">
I have tried changing base-href and deploy-url in the build script, as well as omitting them entirely. I'm just not sure what I'm missing at this point.
Any help would be appreciated, and just ask if you need more information.
Edit:
The application exists at https://clwd0002278/ControlTower/NICK/UI/ and NOT at https://clwd0002278/.
Add
<head>
<base href="/ControlTower/NICK/UI">
...
</head>
to your index.html
or provide int in AppModule like
import { APP_BASE_HREF } from '#angular/common';
...
providers: [{APP_BASE_HREF, useValue: '/ControlTower/NICK/UI'}]
See also
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
https://angular.io/api/common/APP_BASE_HREF
Always your default route must be at the before the path "**".
{path: '404', component: NotFoundComponent},
{path: '', redirectTo: 'patients', pathMatch: 'full'},
{path: '**', component: NotFoundComponent},
Refer
https://angular.io/guide/router
So, it turns out that there was some code from ngrx that was pulled in from our base project package that kept throwing the location.pathname onto the end of the url for the angular/ngrx routing packages. I'm so frustrated and yet so relieved to have finally resolved this issue.
I commented out the reducers and initial state related to this to solve my issue. So, be careful of how ngrx interacts with your url!
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.
I am trying to implement lazy loading for a module. This module has a bunch of child routes with a unique outlet name. This doesn't seem to work when I try to visit the routes.
This can be seems from this example that I saved: https://plnkr.co/edit/NNXAoZItM00RIIxzemts?p=preview
You can see that I have the child route set to
{ path: 'list', component: HeroListComponent, outlet: 'abc' },
in hero-routing.module.ts
and router outlet to:
<router-outlet name="abc"></router-outlet>
in hero.component.ts
I should be able to visit localhost:3000/heroes/(abc:list) when I am running it locally, but it doesn't seem to work.
Note: You can run the plunker example locally by download the zip file and running npm install then npm start.
The child routes do not seem to work with default unamed routes.
Change the lazy loaded module routes to include a redirect from default unamed route to a named route.
const routes: Routes = [
{ path: '', redirectTo: 'start', pathMatch: 'full' },
{ path: 'start', component: HeroComponent,
children: [
{ path: 'list', component: HeroListComponent, outlet: 'abc' },
{ path: ':id', component: HeroDetailComponent }
]
}
];
Finally change the navigation link for 'heroes' lazy loaded module to include the named outlet information. Be sure to specify the complete url as '/heroes/start', do not leave it to the default '/heroes'.
<a [routerLink]="['/heroes/start',{outlets: {abc:['list']}}]"
routerLinkActive="active">Heroes</a>
could you please how to make separate module in angular 2 ?I make a simple example of angular in which user on button click show second page. But now I want to move my code in separate module in angular where I will write separaterouting and components
I try like this
https://plnkr.co/edit/Vm4OXXCCqCI0uTvGdORn?p=preview
I make separate module and routing file
const routes =[
{
path: 'sd',
component: Second
},
{
path: '**', redirectTo: ''
}
]
module file
#NgModule({
imports: [RouterModule.forChild(routes)],
declarations: [ Second],
})
export class SecondModule {}