[6] Basic knowledge of angular routing Passing data while routing redirecting routing subrouting auxiliary routing routing guard

Keywords: angular socket snapshot

 

Routing Basics

Introduction of Routing Related Objects

 

 

Create a new project

ng new router --routing

And use webstrom to open

It is found that after the routing parameter is created, there will be an additional file app-routing.module.ts, which is the path configuration of the current application.

The contents are as follows

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

const routes: Routes = [];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

app.module.ts will also import this module

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.html also has one more socket

<router-outlet></router-outlet>

 

To demonstrate the functionality, create two components first

ng g component home

ng g component product

Modify home.component.html

<p>
  Here is the home page component
</p>

product.component.html

<p>
  This is the commodity information component.
</p>

Modify app.component.html

<!--The content below is only a placeholder and can be replaced.-->
<a [routerLink]="['/']">homepage</a>
<a [routerLink]="['/product']">Commodity details</a>

<router-outlet></router-outlet>

Running View Effect

When choosing goods, the above address will automatically become http://localhost:4200/product

Add a button and use the controller to jump

<!--The content below is only a placeholder and can be replaced.-->
<a [routerLink]="['/']">homepage</a>
<a [routerLink]="['/product']">Commodity details</a>
<button type="button" value="Commodity details" (click)="toProDuctDetails()" >Commodity details</button>
<router-outlet></router-outlet>

Modify app.component.ts

import {Component} from '@angular/core';
import {Router} from '@angular/router';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'router';

  constructor(private router: Router) {
  }

  toProDuctDetails() {
    this.router.navigate(['/product']);
  }
}

The effect is the same as routerLink

When users use non-existent paths

Create a 404 component

ng g component code404

Modify code404.component.html

<p>
  Page does not exist
</p>

Modify app-routing.module.ts

import {NgModule} from '@angular/core';
import {Routes, RouterModule} from '@angular/router';
import {HomeComponent} from './home/home.component';
import {ProductComponent} from './product/product.component';
import {Code404Component} from './code404/code404.component';

const routes: Routes = [
  {path: '', component: HomeComponent},
  {path: 'product', component: ProductComponent},
  {path: '**', component: Code404Component},
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {
}

The visit was wrong. http://localhost:4200/produ1

Error interfaces can also occur

 

Transfer data while routing

Passing data when querying parameters

/product?id=1&name=2   >>  ActivatedRoute.queryParams[id]

Transfer data in routing paths

{path:/product/:id} >>  /product/1  ActivatedRoute.params[id]

Transfer data in routing configuration

 {path:/product,comonent:ProductCompomemt,data[{isProd:true}]} >> ActivatedRoute.data[0][isProd]

Now let's continue to modify demo to see the effect.

 app.component.html

<!--The content below is only a placeholder and can be replaced.-->
<a [routerLink]="['/']">homepage</a>
<a [routerLink]="['/product']" [queryParams]="{id:1}">Commodity details</a>
<button type="button" value="Commodity details" (click)="toProDuctDetails()" >Commodity details</button>
<router-outlet></router-outlet>

product.component.ts

import {Component, OnInit} from '@angular/core';
import {ActivatedRoute} from '@angular/router';

@Component({
  selector: 'app-product',
  templateUrl: './product.component.html',
  styleUrls: ['./product.component.css']
})
export class ProductComponent implements OnInit {
  public productId: number;

  constructor(private routeInfo: ActivatedRoute) {
  }

  ngOnInit() {
    this.productId = this.routeInfo.snapshot.queryParams['id'];
  }

}
<p>
  This is the commodity information component.
</p>
<p> Commodity Id is {productId}</p>

Here's the second way

app.component.html

<!--The content below is only a placeholder and can be replaced.-->
<a [routerLink]="['/']">homepage</a>
<a [routerLink]="['/product',1]" >Commodity details</a>
<button type="button" value="Commodity details" (click)="toProDuctDetails()" >Commodity details</button>
<router-outlet></router-outlet>

app-routing.module.ts

import {NgModule} from '@angular/core';
import {Routes, RouterModule} from '@angular/router';
import {HomeComponent} from './home/home.component';
import {ProductComponent} from './product/product.component';
import {Code404Component} from './code404/code404.component';

const routes: Routes = [
  {path: '', component: HomeComponent},
  {path: 'product/:id', component: ProductComponent},
  {path: '**', component: Code404Component},
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {
}

product.component.ts

import {Component, OnInit} from '@angular/core';
import {ActivatedRoute} from '@angular/router';

@Component({
  selector: 'app-product',
  templateUrl: './product.component.html',
  styleUrls: ['./product.component.css']
})
export class ProductComponent implements OnInit {
  public productId: number;

  constructor(private routeInfo: ActivatedRoute) {
  }

  ngOnInit() {
    this.productId = this.routeInfo.snapshot.params['id'];
  }

}

In writing the third way, we need to clarify two concepts: parameter snapshots and parameter subscriptions.

Modify app.component.ts

import {Component} from '@angular/core';
import {Router} from '@angular/router';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'router';

  constructor(private router: Router) {
  }

  toProDuctDetails() {
    this.router.navigate(['/product', 2]);
  }
}

Then operate the web page

The above homepage, commodity details (p) commodity details (button), which we call 123

Click 1. Click 3. The effect is normal.

Click 1 and click 2. The effect is normal.

Click 1, click 2, click 3 as shown above.

This is because of the product.component.ts

  ngOnInit() {
    this.productId = this.routeInfo.snapshot.params['id'];
  }

Parametric snapshots are used.

Let's try parameter subscription instead.

import {Component, OnInit} from '@angular/core';
import {ActivatedRoute, Params} from '@angular/router';

@Component({
  selector: 'app-product',
  templateUrl: './product.component.html',
  styleUrls: ['./product.component.css']
})
export class ProductComponent implements OnInit {
  public productId: number;

  constructor(private routeInfo: ActivatedRoute) {
  }

  ngOnInit() {
    this.routeInfo.params.subscribe((params: Params) => this.productId = params['id']);
  }

}

We will find that even if we click 1 click 2 Click 3, the effect will be fine.

Redirection Route

When a user accesses a specific address, redirect it to another specified address.

www.aaa.com  >> www.aaa.com/products
www.aaa.com/x >> www.aaa.com/y

Modify routing configuration

import {NgModule} from '@angular/core';
import {Routes, RouterModule} from '@angular/router';
import {HomeComponent} from './home/home.component';
import {ProductComponent} from './product/product.component';
import {Code404Component} from './code404/code404.component';

const routes: Routes = [
  {path: '', redirectTo: '/home', pathMatch: 'full'},
  {path: 'home', component: HomeComponent},
  {path: 'product/:id', component: ProductComponent},
  {path: '**', component: Code404Component},
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {
}

Subrouter

{path:'home',component:HomeComponent}

 -----------------------------------------------------------------

{path:'home',component:HomeComponent,
 children:[

{path:'',component:XxxComponent,},
{path:'/yyy' compenent:YyyComponent}
]
}

Templates of Home components are still displayed when accessing the home path, but

router-outlet displays the Xxx pricing template

Similarly, when visiting home/yyy, the template of the Home component will still be displayed, but

router-outlet displays Yyy pricing template

Now let's step by step implement subrouting

Create two new components

ng g component productDesc

ng g component sellerInfo

app-routing.module.ts

import {NgModule} from '@angular/core';
import {Routes, RouterModule} from '@angular/router';
import {HomeComponent} from './home/home.component';
import {ProductComponent} from './product/product.component';
import {Code404Component} from './code404/code404.component';
import {ProductDescComponent} from './product-desc/product-desc.component';
import {SellerInfoComponent} from './seller-info/seller-info.component';

const routes: Routes = [
  {path: '', redirectTo: '/home', pathMatch: 'full'},
  {path: 'home', component: HomeComponent},
  {
    path: 'product/:id', component: ProductComponent,
    children: [
      {path: '', component: ProductDescComponent},
      {path: 'seller/:id', component: SellerInfoComponent},
    ]
  },
  {path: '**', component: Code404Component},
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {
}

seller-info.component.ts

import {Component, OnInit} from '@angular/core';
import {ActivatedRoute} from '@angular/router';

@Component({
  selector: 'app-seller-info',
  templateUrl: './seller-info.component.html',
  styleUrls: ['./seller-info.component.css']
})
export class SellerInfoComponent implements OnInit {
  public sellerId: number;

  constructor(private routeInfo: ActivatedRoute) {
  }

  ngOnInit() {
    this.sellerId = this.routeInfo.snapshot.params['id'];
  }

}

seller-info.component.html

<p>
  The salesperson ID is {sellerId}
</p>

product-desc.component.html

<p>
  This is a fork.
</p>

product.component.html

<p>
  This is the commodity information component.
</p>
<p> Commodity Id is {productId}</p>
<a href=""[routerLink]="['. /']">Product Description</a>
<a href=""[routerLink]="['. / seller', 99]"> Salesperson Information</a>
<router-outlet></router-outlet>

Subrouting can not only nest two layers, but also nest down infinitely with the complexity of demand

Auxiliary routing

Configuration is divided into three steps
<router-outlet></router-outlet>
<router-outlet name="aux"></router-outlet>

{path: 'xxx',component: XxxComponent,outlet: 'aux'}
{path: 'yyy',component: YxxComponent,outlet: 'aux'}


<a[routerLink]="['/home',{outles:{aux: 'xxx'}}]">Xxx</a>
<a[routerLink]="['/product',{outles:{aux: 'yyy'}}]">Yyy</a>

Overall thinking of auxiliary routing cases

Define another socket on the template of the app component to display the chat panel

Develop a chat plug-in separately and display it only on the newly defined socket

Controlling whether the new socket displays the chat panel through routing parameters

ng g component chat

chat.component.html

<textarea placeholder="Please enter the chat content" class="chat"></textarea>
.chat{
  background: aquamarine;
  height: 100px;
  width: 30%;
  float: left;
  box-sizing: border-box;
}

home.component.html

.home{
  background: red;
  height: 100px;
  width: 70%;
  float: left;
  box-sizing: border-box;
}

product.component.html

<div class="product">
  <p>
    This is the commodity information component.
  </p>
  <p> Commodity Id is {productId}</p>
  <a href=""[routerLink]="['. /']">Product Description</a>
  <a href=""[routerLink]="['. / seller', 99]"> Salesperson Information</a>
  <router-outlet></router-outlet>

</div>

product.component.css

.product{
  background: yellow;
  height: 100px;
  width: 70%;
  float: left;
  box-sizing: border-box;
}

app-routing.module.ts

import {NgModule} from '@angular/core';
import {Routes, RouterModule} from '@angular/router';
import {HomeComponent} from './home/home.component';
import {ProductComponent} from './product/product.component';
import {Code404Component} from './code404/code404.component';
import {ProductDescComponent} from './product-desc/product-desc.component';
import {SellerInfoComponent} from './seller-info/seller-info.component';
import {ChatComponent} from './chat/chat.component';

const routes: Routes = [
  {path: '', redirectTo: '/home', pathMatch: 'full'},
  {path: 'chat', component: ChatComponent, outlet: 'aux'},
  {path: 'home', component: HomeComponent},
  {
    path: 'product/:id', component: ProductComponent,
    children: [
      {path: '', component: ProductDescComponent},
      {path: 'seller/:id', component: SellerInfoComponent},
    ]
  },
  {path: '**', component: Code404Component},
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {
}

app.component.html

<!--The content below is only a placeholder and can be replaced.-->
<a [routerLink]="['/']">homepage</a>
<a [routerLink]="['/product',1]">Commodity details</a>
<button type="button" value="Commodity details" (click)="toProDuctDetails()">Commodity details</button>

<a [routerLink]="[{outlets:{ primary: 'home',aux:'chat'}}]">Start chatting</a>
<a [routerLink]="[{outlets:{aux:null}}]">End chat</a>

<p>
  <router-outlet></router-outlet>
  <router-outlet name="aux"></router-outlet>
</p>

primary:'home'is used to display home every time you switch to the chat component.

Routing guard

Use scenarios

  • Only when the user has logged in and has certain privileges can he enter certain routes.
  • A wizard consisting of multiple form components, such as a registration process, allows users to navigate to the next route only if they fill in the required information in the component of the current route.
  • Remind users when they attempt to leave the current navigation without performing a save operation.

You can use hooks to do this.

There are three kinds of routing guards

  • CanActivate: Handles navigation to a route.
  • CanDeactivate: Handles current routing departures.
  • Resolve: Get routing data before routing is activated.

 

Let's continue to modify the case below. Only when the user has logged in and has some privileges can he enter the product routing.

Create a new guard folder under the app directory and a new login.guard.ts

import {CanActivate} from '@angular/router';

export class LoginGuard implements CanActivate {
  canActivate() {
    const loggedIn: boolean = Math.random() < 0.5;
    if (!loggedIn) {
      console.log('User not logged in');
    }
    return loggedIn;
  }

}

Modify routing app-routing.module.ts

import {NgModule} from '@angular/core';
import {Routes, RouterModule} from '@angular/router';
import {HomeComponent} from './home/home.component';
import {ProductComponent} from './product/product.component';
import {Code404Component} from './code404/code404.component';
import {ProductDescComponent} from './product-desc/product-desc.component';
import {SellerInfoComponent} from './seller-info/seller-info.component';
import {ChatComponent} from './chat/chat.component';
import {LoginGuard} from './guard/login.guard';
import {UnsavedGuard} from './guard/Unsaved.guard';

const routes: Routes = [
  {path: '', redirectTo: '/home', pathMatch: 'full'},
  {path: 'chat', component: ChatComponent, outlet: 'aux'},
  {path: 'home', component: HomeComponent},
  {
    path: 'product/:id', component: ProductComponent,
    children: [
      {path: '', component: ProductDescComponent},
      {path: 'seller/:id', component: SellerInfoComponent},
    ], canActivate: [LoginGuard],
  
  },
  {path: '**', component: Code404Component},
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
  providers: [LoginGuard],
})
export class AppRoutingModule {
}

That leaves only a 50% chance of getting into commodity routing.

Let's create a new CanDeactivate: to handle the current routing departure.

New Unsaved.guard.ts under guard file

import {CanDeactivate} from '@angular/router';
import {ProductComponent} from '../product/product.component';

export class UnsavedGuard implements CanDeactivate<ProductComponent>{
  canDeactivate(component: ProductComponent) {
    return window.confirm('You haven't saved it yet. Are you sure you want to leave??');
  }

}

Modify the routing configuration of app-routing.module.ts

import {NgModule} from '@angular/core';
import {Routes, RouterModule} from '@angular/router';
import {HomeComponent} from './home/home.component';
import {ProductComponent} from './product/product.component';
import {Code404Component} from './code404/code404.component';
import {ProductDescComponent} from './product-desc/product-desc.component';
import {SellerInfoComponent} from './seller-info/seller-info.component';
import {ChatComponent} from './chat/chat.component';
import {LoginGuard} from './guard/login.guard';
import {UnsavedGuard} from './guard/Unsaved.guard';

const routes: Routes = [
  {path: '', redirectTo: '/home', pathMatch: 'full'},
  {path: 'chat', component: ChatComponent, outlet: 'aux'},
  {path: 'home', component: HomeComponent},
  {
    path: 'product/:id', component: ProductComponent,
    children: [
      {path: '', component: ProductDescComponent},
      {path: 'seller/:id', component: SellerInfoComponent},
    ], canActivate: [LoginGuard],
    canDeactivate: [UnsavedGuard],
  },
  {path: '**', component: Code404Component},
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
  providers: [LoginGuard, UnsavedGuard],
})
export class AppRoutingModule {
}

A dialog box pops up when you leave the product to another component.

 

Use Resolve Guard below

Create product.resolve.ts under guard file

The code is as follows

///<reference path="../../../node_modules/@angular/core/src/di/injectable.d.ts"/>
import {ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot} from '@angular/router';
import {Product} from '../product/product.component';
import {Observable} from 'rxjs';
import {Injectable} from '@angular/core';

/**
 * // This class needs a decorator to decorate it.

 */
@Injectable()
export class ProductResolve implements Resolve<Product> {
  constructor(private router: Router) {

  }

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Product> | Promise<Product> | Product {
    let productId: number = route.params['id'];
    if (productId == 1) {
      return new Product(1, 'iPhoneX');
    } else {
      this.router.navigate(['/home']);
      return undefined;
    }
  }

}

product.component.html

<div class="product">
  <p>
    This is the commodity information component.
  </p>
  <p> Commodity Id is {productId}</p>
  <p> The name of the commodity is {productName}</p>
  <a href=""[routerLink]="['. /']">Product Description</a>
  <a href=""[routerLink]="['. / seller', 99]"> Salesperson Information</a>
  <router-outlet></router-outlet>

</div>

product.component.ts

import {Component, OnInit} from '@angular/core';
import {ActivatedRoute, Params} from '@angular/router';

@Component({
  selector: 'app-product',
  templateUrl: './product.component.html',
  styleUrls: ['./product.component.css']
})
export class ProductComponent implements OnInit {
  public productId: number;
  public productName: string;

  constructor(private routeInfo: ActivatedRoute) {
  }

  ngOnInit() {
    this.routeInfo.params.subscribe((params: Params) => this.productId = params['id']);
    this.routeInfo.data.subscribe((data: { product: Product }) => {
      this.productId = data.product.id;
      this.productName = data.product.name;
    });
  }

}

export class Product {
  constructor(public id: number, public name: string) {
  }
}

app-routing.module.ts

import {NgModule} from '@angular/core';
import {Routes, RouterModule} from '@angular/router';
import {HomeComponent} from './home/home.component';
import {ProductComponent} from './product/product.component';
import {Code404Component} from './code404/code404.component';
import {ProductDescComponent} from './product-desc/product-desc.component';
import {SellerInfoComponent} from './seller-info/seller-info.component';
import {ChatComponent} from './chat/chat.component';
import {LoginGuard} from './guard/login.guard';
import {UnsavedGuard} from './guard/Unsaved.guard';
import {ProductResolve} from './guard/product.resolve';

const routes: Routes = [
  {path: '', redirectTo: '/home', pathMatch: 'full'},
  {path: 'chat', component: ChatComponent, outlet: 'aux'},
  {path: 'home', component: HomeComponent},
  {
    path: 'product/:id', component: ProductComponent,
    children: [
      {path: '', component: ProductDescComponent},
      {path: 'seller/:id', component: SellerInfoComponent},
    ], resolve: {product: ProductResolve}
  },
  {path: '**', component: Code404Component},
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
  providers: [LoginGuard, UnsavedGuard, ProductResolve],
})
export class AppRoutingModule {
}

Do you remember the 123 we named earlier?

When you click on 1, the home page clicks on 2 and enters id 1, so when you can go in and display Apple 7 clicks on 3, you enter id 2, so the display fails.

Download items

Posted by ejwf on Wed, 08 May 2019 23:03:39 -0700