Angular2 useAsDefault not work for child route - javascript

I have been playing around with Angular2 route example which has child route as default route, but the example did not navigate to that default route: https://angular.io/resources/live-examples/tutorial/ts/plnkr.html
While the tutorial of Tour of Heroes which has not child route, useAsDefault was working normally: https://angular.io/resources/live-examples/router/ts/plnkr.html
Any sollution would be appreciated. Thanks in advance

Apparently nested useAsDefaults don't work, I'm not aware of that behavior. Note too that the problem is the useAsDefault in the parent route, not in the child.
You can fix that issue though by adding a redirectTo.
#RouteConfig([
{ path : '/', redirectTo : ['CrisisCenter'] }, // Here...
{ // Crisis Center child route
path: '/crisis-center/...',
name: 'CrisisCenter',
component: CrisisCenterComponent
},
{path: '/heroes', name: 'Heroes', component: HeroListComponent},
{path: '/hero/:id', name: 'HeroDetail', component: HeroDetailComponent},
{path: '/disaster', name: 'Asteroid', redirectTo: ['./CrisisCenter', 'CrisisDetail', {id:3}]}
])
export class AppComponent { }
Note that I removed the extra useAsDefault. I'll file an issue so they can fix it in the docs.
Update 2
It isn't a mistake in the docs actually, it's a bug. I got the confirmation by #wardbell. There's already an issue filed for this bug.
So according to his comment the docs won't be updated (there's nothing to update, it's a bug!).
This issue was reported [...]. I left the doc as is, hoping that it will become correct soon.
Update
Here's the issue I filed. They'll tell us if it's a mistake in the docs or not (most likely, I'll bet on that). I'll update after they answer.

Related

Change name of route path in browser only

I need to write two different routes to two pages like
{ path: 'abc', component: abcComponent},
{ path: 'abc2', component: abcComponent2},
as browser show me path:
http://localhost:4200/abc2 on accessing second route path.
Can I somehow have the same name for two components ie I want the browser to display only
http://localhost:4200/abc even if calling route path: 'abc2';
Please help me. Thanks in advance
I don't know why you need this, but if you want to do that just paste this line of code in constructor of abcComponent2 constructor:
this.router.navigateByUrl('abc', { skipLocationChange: true });
or you can also change router without changing location via html like this:
<a [routerLink]="..." skipLocationChange>click me</a>

Navigate between outlet modals in Angular 5?

I can't handle navigation from one modal window to another.
I have routing module:
{
path: 'modal1',
component: Modal1Component,
outlet: 'modal',
}, {
path: 'modal2',
component: Modal2Component,
outlet: 'modal',
}
Main component: MainComponent and in its template i have
<router-outlet name="modal"></router-outlet>
So i am clicking a button that triggers
this.router.navigate([this.router.url, { outlets: {modal: 'modal1'} }]);
And in Modal1Component that is rendered i have a button for modal2. So i want to call modal2 from modal1. How can i tell router to go to the parent route and then call:
this.router.navigate([/* what should be here? */, { outlets: {modal: 'modal2'} }]);
It looks like you're just changing the outlet in your router.navigate, but the route itself is not actually changing. And I don't think you actually require a named outlet to do what you're trying to achieve.
When you use router.navigate, you can specify if you want to navigate relatively from somewhere using the ActivatedRoute class. To do so, you have two options :
navigate relatively from you current component and indicate in the path that you want to "go up" one level. Example :
this.router.navigate(['../modal2'], { relativeTo: this.activatedRoute });
navigate directly from you parent. I would personaly use this one but both works. Example :
this.router.navigate(['modal2'], { relativeTo: this.activatedRoute.parent });
I created a mini repo with an example of what (I think) you're trying to achieve on : stackblitz.
Hope that helps
Some service can be useful in this case, like in doc:
https://angular.io/guide/component-interaction

refreshing a detail page in Aurelia results in blank

I have created a new sample app with aurelia-cli.
A weird behaviour that got me stuck is with routing.
This is my main route.
{
route: "projects",
title: 'Project Section',
name:'project-section',
moduleId: './modules/projects/project-section',
nav: true
}
and this is my project-section file
export class ProjectSection {
configureRouter(config, router) {
config.map([
{ route: '', moduleId: './projects-list', nav: false, title: 'Projects List' },
{ route: ':id', moduleId: './project-detail', nav: false, title: 'Project Detail' }
]);
this.router = router;
}
}
now when I open a link like http://myapp.com/projects, it works fine, and if I refresh the page, it still works.
If I click a link to open the detail page http://myapp.com/projects/9348 that also works fine. But on refreshing this detail page, browser goes blank with
GET http://localhost:9000/projects/scripts/vendor-bundle.js net::ERR_ABORTED
error message in console
Am I missing something obvious? Is there a config setting to enable the refreshing of pages with /:id like routes?
The code is here at github aurelia-sample and you clone and run as usual
au run --watch
Thanks for any help
EDIT: does it have anything to do with
config.options.pushState = true;
in the app config?
I don't know if your problem has been resolved. But Yes, it is to do with the pushState being set to true. I myself faced this issue before. It is something to do with how Aurelia loads the JS for the page. I was unable to resolve it (albeit I'll admit I looked only for about 20 mins). But from what I saw you need to configure some setting to make this work.
Ok. This will help http://aurelia.io/docs/routing/configuration#options.
Baiscally:
Add a <base href="http://localhost:9000"> to index.html to redirect loading content from the base url. The rest of the configuration can be as you have kept it.
Also add config.options.root = '/' in your router config
The point that you are missing is that, (IMHO kind of counterintuitively), the subroutes defined by ProjectsSection only come to life once you actually navigate to /projects.
In other words, the following sequence works:
navigate to projects-list component (route of '' relative to the route of the section, that is, projects/ relative to the app)
Refresh that same page
Navigate to a details page.
The reason this sequence works has to do with how Aurelia resolves routes.
It first tries to match your route against the root configuration. It sees that the url starts with projects. So it checks to which component projects leads. It is ProjectSection in your case, therefore it uses that and checks whether it finds a configureRouter method on it. It does, because you've defined one, so it invokes it.
From then on, the route that it will try to match against that configuration is the the original route without the prefix which lead to that component. It was projects/ which lead to ProjectSection, followed by nothing, so the remainder of the route is / which is resolved as per the configuration you've created inside ProjectSection. In your case, that leads to projects-list.
The important part about this is that by performing this sequence, Aurelia gets a chance to invoke the configureRouter method on ProjectSection (since at (2), it navigates once again to projects/ relative to the app root). Therefore, a configuration which can be used against the url will exist.
In the problematic case, if you immediately navigate to /projects/:id, it will be matched against the root level configuration. There is no match, and since reloading counts as a first page load, there is no route to fall back to. That's why you are getting the error.
The important part about this scenario is that, contrary to the former case, the router skips invoking the configureRouter method on ProjectSection. If you set a breakpoint in that method, you will see that it does not get invoked. That's why I commented on is behavior as being counter-intuitive, because the behavior you (and me as well, when I first faced this problem) expect is a fairly common scenario.
I don't know of any official way to resolve this, so my suggestion is that you could try defining a wildcard route on the app level config like so:
{
route: "projects/*",
title: 'Project Section',
name:'project-section',
moduleId: './modules/projects/project-section',
nav: true
}
and see if it works (I am not sure - I've tried to provide you with a reason, but I don't have the means to try to reproduce it at this very moment).
Try adding a redirect route in the ProjectSection configureRouter function like so (taking your example):
export class ProjectSection {
configureRouter(config, router) {
config.map([
{ route: '', redirect: 'list' }, // Redirects to the list route when no specific route in the project section is specified
{ route: 'list', moduleId: './projects-list', nav: false, title: 'Projects List' },
{ route: ':id', moduleId: './project-detail', nav: false, title: 'Project Detail' }
]);
this.router = router;
}
}
Thanks for all the answers posted. I finally resolved the issue. I am still not sure if this is the right way or not but here is the trick that works.
Taking hint from Rud156's and answer from this question How to remove # from URL in Aurelia I just added
<base href="/">
in the index.html file, and everything works as expected.
To further investigate the issue I cloned the aurelia sample contact app
1- when you run the app as it is after cloning, everything works great.
2- if you add
config.options.pushState = true;
in the src/app.js, child routes will stop working.
3- Add
<base href="/">
in the index.html and everything will start working.

Rendering a child route in the parent in Angular 4

With Angular 2, I could make a child route render "over" its parent by defining an empty path and creating an essentially empty base component. I am trying to accomplish something similar with the new Angular router (version 4.3.1), but have hit a roadblock.
To reproduce my problem, here's a Plunker. The routes are defined as:
[{
path: '',
redirectTo: "/master",
pathMatch: "full"
}, {
path: 'master',
component: MasterComponent,
children: [{
path: 'detail/:value',
component: DetailComponent,
children: [{
path: 'subdetail',
component: SubDetailComponent
}]
}]
}]
When I navigate to a detail page, the master page is still visible because I have added a <router-outlet></router-outlet> to MasterComponent. What I need is to replace the master view with the detail. I can accomplish this by making detail/:value a sibling of master rather than a child, but this isn't logically correct in my application and breaks my breadcrumbs.
Is there any proper way to handle this kind of pattern, or will I have to pick a workaround, such as showing and hiding the intended route or manually specifying a dedicated "main" outlet for every link?
The only existing solution that comes close is to define a dummy parent component, but this only works one-level down. If my detail page has another sub-detail page that should also replace master, it gets very messy.
Is there any route-level flag I can set or design pattern to implement to elegantly accomplish this? I am an Angular 2 beginner, but I feel as though something like this should be simple.
First, there is no "new" router in 4.3.1. It's the same router from 2.x.
Second, there were a few changes I needed to make to your plunker to make it work appropriately. The key change was this in the master.component.ts:
<a [routerLink]="['/detail', 5]">
I added a slash. Without the slash it was looking for a route named master/detail/5
The route definition is now flat, so everything will appear "under" your main header.
export const routes: Routes = [
{
path: '',
redirectTo: 'master',
pathMatch: 'full'
},
{
path: 'master',
component: MasterComponent
},
{
path: 'detail/:value',
component: DetailComponent
}
];
The updated plunker is here: https://plnkr.co/edit/EHehUR6qSi248vQPDntt?p=preview

Routing behavior not working as expected

I have the following routes variable defined in my app-routing.module.ts:
const routes: Routes =
[
{ path: '', redirectTo: '/users', pathMatch: 'full' },
{ path: 'users', component: UsersComponent },
{ path: 'dashboard', component: DashboardComponent }
];
With this current configuration, when I submit http://localhost:3000/users, the browser redirects to http://localhost:3000/users/users and then displays the user list binding in the html as expected.
However, something seems off kilter for the browser to redirect from /users to /users/users. If I remove the th first route config with the redirectTo attribute then the browser stays on /users without redirecting to /users/users. However, in this scenario, the user list binding doesn't display as expected.
Any idea what might be causing the redirect to /users/users? Any idea how I can keep the browser on /users and get the user list binding to properly display at this uri?
Option 1: Setting base tag
In order to get the router working properly a base href needs to be defined somehow for the app. The docs recommend adding a base element to the head of your index.html file, such as:
<base href="/">
Option 2: Setting a provider
This can be a bit dangerous however as it has (potentially unexpected) side effects on anchor tags, empty href tags, etc, etc. It also breaks inline svg sprites... which was a major part of our app's UI. If you want to make the router work but not break a lot of things you can actually define the base href elsewhere, like so:
// ... other imports
import { APP_BASE_HREF } from '#angular/common';
#NgModule({
// ... other pieces of ngModule
providers: [
{provide: APP_BASE_HREF, useValue : '/' }
],
// ... other pieces of ngModule
})
export class AppModule {
constructor() {}
}
As a basic example. It's a bit hard to find in the documentation but is a good workaround to get things going without messing with everything else.

Categories