how to use routerlink in angular? - javascript

I'm new in Angular but I came from various frameworks that are relevant to the Backend such as Django, I note that Angular has the same nature as Django routing a bit regardless that it belongs to client-side so, so I'm familiar with routing confused around how Angular handles routing and use router-link in the template in Angular.
there is my problem:
export const routes: Routes = [
{path: 'login', component: LoginComponent, outlet: "login"},
{path: 'signup', component: RegisterComponent, outlet: "register"},
]
when I'm trying to move to the login page by the following statement:
<a [routerLink]="['', {outlets: {login: ['login']}}]" ariaCurrentWhenActive="page" routerLinkActive="active">Signin?</a>
what is happening is that the link looks like this link when it displaying it in the inspect element:
/app/(login:login//register:signup)
my current page is /app/(register:signup) and all I want to do is to move to: /app/(login:login)
first of all, I want to know how to move to my target.
second: I want to understand the router link nature in angular and how it works if it is possible.

Related

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

Angular 5: How to load multiple custom child components for a screen?

Background
I'm writing an enterprise application in Angular 5. One of the large screens I'm working on has many tabs and child components. A majority of clients will get the same version of the screen, but a client or two want custom changes under a couple of tabs.
Question
How do I dynamically load custom components for those couple of tabs where the client wants changes? I know I could use async lazy module loading to load a whole new screen specific for that client, but it seems it would be more efficient to only swap out the child components that have changes rather than the whole screen.
Async loading appears to be the way to go as you can use canLoad to not load unnecessary code for each client. At the child level, if you have multiple components at the same child level to swap, you could try to use named router outlets with async modules for the child components. However, I ran into a bug with async loading and the named router outlets.
Anyone have any other ideas?
Code
Here is the code for the routes I tried when exploring the above idea. The core screen is the parent level screen, async loaded.
export const routes: Routes = [
{
path: '',
component: CoreScreenComponent,
children: [
{
path: 'x-core',
loadChildren: "app/components/core-component-x/core-component-x.module#CoreComponentXComponent",
outlet: 'x'
},
{
path: 'x-client',
loadChildren: "app/components/client-component-x/client-component-x.module#ClientComponentXComponent",
outlet: 'x'
},
{
path: 'y-core',
loadChildren: "app/components/core-component-y/core-component-y.module#CoreComponentYComponent",
outlet: 'y'
},
{
path: 'y-client',
loadChildren: "app/components/client-component-y/client-component-y.module#ClientComponentyComponent",
outlet: 'y'
},
]
}];

angular's equivalent to angularjs states

In AngularJS, for routing purposes, we define states with children which makes it possible to switch between views with the result that each view is always rendered in one container:
$stateProvider.state("communication.create-message", {
url: ...,
templateUrl: ...,
menu: ...,
parent: "communication",
ncyBreadcrumb: {
label: "Create Message"
}
});
Whichever state we choose - the view is always rendered within one container that has ui-view attribute.
I'm trying to achieve the same in Angular 2 or above, but I have no idea of how to reproduce the above-stated functionality.
In app.component.ts we have router-outlet where component templates get rendered.
Say, we have many nested child routes - is it possible to render all of them within this outlet ?
What would the code in app-routing.module.ts look like in this case ?
Could anyone please give a working example of how to go about it ?
Step 1 : Import Routes from #angular/router
in app.module.ts .. import Routes. You have to write
import {Routes} from '#angular/core'
Step 2 :
Add all the routes you want to set up in an array pf type Routes like :
this is for informing angular all the routes in your app. Each route is a javascript object in this array.
const appRoutes : Routes = [
{path : 'communication-route'}
]
always you have to give path , this what you enter after your domain like "localhost :4200/communication-route".
Step 3: Add the action to route i.e what happens when this path is reached.
const appRoutes : Routes = [
{path : 'communication-route'} , component :communicationroutecomponent
]
here i have given the component name "communicationroutecomponent" , i.e this component will be loaded when the path "/communication-route" is reached
Step 4: Register your routes in your app
To do this you will have to do new import in app.module.ts
import {RouterModule} from '#angular/router'
Routermodule has special method forRoot() which registers our routes .
In our case we will have to write this piece of code in
imports :[
RouterModule.forRoot(appRoutes)
]
Our routes are now registered and angular knows our routes now.
Step 5 : Where to display the route content i.e the html content of you route page.
For this angular has directive .
We need to include where we want to load our content i.e in the html.
<a router-outlet="/communication-route"></a>
Navigating to routes :
angular gives a directive for this routerLink
so if we want to navigate to users component , you can give this in your html element:
routerLink="/communication-route"
I hope i was able to explain how this works.
Your code should be as follows
export const ComRoute: Routes = [
{
path: 'communication-route',
children: [
{ path: 'communication', component: communicationComponent },
{ path: ':child1', component: child1Component },
{ path: ':child1/field', component: child1Component}
]
}
];
First of all, states are not an official AngularJS concept. They come from ui-router, which began life as an alternate to the simplistic built in router.
Eventually, ui-router became the de facto standard for routing in AngularJS while the official ng-route module was extracted into a separate, optional library by the Angular team.
ui-router, is complex but exceptional and has earned what is in my view well deserved popularity and success. This success has led to its expansion to support additional platforms enabling the same powerful state based structure in applications written for frameworks such as React.
It is now available for Angular (formerly known as Angular 2).
You can read the documentation and see how to get started on https://ui-router.github.io/ng2
Here is a snippet from the src/app/app.states.ts module of the official example repository
export const loginState = {
parent: 'app',
name: 'login',
url: '/login',
component: LoginComponent,
resolve: [
{ token: 'returnTo', deps: [Transition], resolveFn: returnTo },
]
};
As we can see, there are compatible concepts available, including what looks like a nice evolution of the resolves API which allows function oriented injection which was generally simpler than class based injection in ui-router with AngularJS.
Note, I have not used it in an Angular project.

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